Chameleon

Chameleon Commit Details

Date:2015-03-09 21:26:30 (9 years 1 month ago)
Author:zenith432
Commit:2597
Parents: 2596
Message:Sanitize 16-bit assembly
Changes:
M/branches/zenith432/i386/boot2/boot.c
M/branches/zenith432/i386/libsa/interrupts.c
M/branches/zenith432/i386/libsaio/table.c
M/branches/zenith432/i386/boot2/boot2.s
M/branches/zenith432/i386/libsaio/bios.s
M/branches/zenith432/i386/libsaio/saio_internal.h
M/branches/zenith432/i386/libsaio/asm.s
M/branches/zenith432/i386/boot2/mboot.c

File differences

branches/zenith432/i386/libsaio/asm.s
124124
125125
126126
127
128
129
130127
131128
132129
......
150147
151148
152149
153
150
154151
155152
156153
......
161158
162159
163160
164
165161
166162
167163
......
181177
182178
183179
180
184181
185
182
186183
187184
188
185
189186
190187
191188
......
194191
195192
196193
194
195
197196
198197
199198
200199
201200
202201
203
204
205
202
206203
207204
208205
209206
210
211
207
212208
213209
214210
215211
216212
217
218
213
219214
215
216
220217
221218
222219
223220
224
221
225222
226223
227224
......
248245
249246
250247
251
248
252249
253
254
255250
256251
257252
......
276271
277272
278273
274
275
276
279277
280
281278
282279
283280
284281
285282
286283
287
288
284
289285
290286
291287
......
299295
300296
301297
302
303
298
304299
305300
306301
307302
308
309303
310
311304
312305
313306
314307
315308
316
317309
318
319
320
321
322310
323311
324312
325313
326314
327
328
315
329316
317
318
330319
331320
332321
......
345334
346335
347336
348
349
337
338
339
340
341
350342
351
352
353
354
355
343
344
345
356346
357347
358348
359
349
360350
361351
362352
......
386376
387377
388378
389
390
391379
392
393
394
380
395381
396
397
382
383
384
385
386
398387
399388
400
401
389
402390
403
404
405391
406392
407393
408394
409
395
410396
411397
412
398
413399
414
415
416
400
401
402
417403
418404
419405
406
407
420408
421409
422410
......
425413
426414
427415
416
417
428418
429419
430420
......
442432
443433
444434
445
446
435
447436
437
438
448439
449440
450
451
441
452442
453
454
443
455444
445
446
456447
457448
458449
450
459451
460452
461453
#include <architecture/i386/asm_help.h>
#include "memory.h"
#define data32 .byte 0x66
#define addr32 .byte 0x67
.file "asm.s"
CR0_PE_ON = 0x1
.globl _Gdtr
//.data
.section __INIT,__data// turbo - Data that must be in the first segment
.align 2, 0x90
.align 2
_Gdtr:
.word GDTLIMIT
.long vtop(_Gdt)
.section __INIT,__data// turbo - Data that must be in the first segment
// Real mode IDT
.align 2
.globl _Idtr_real
_Idtr_real:
.word 0x03ff
.long 0x00000000
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Data area for __switch_stack.
//
.align 2
save_sp: .long STACK_OFS
save_ss: .long STACK_SEG
save_ss: .word STACK_SEG
//.text
.section __INIT,__text // turbo - This code must reside within the first segment
.section __INIT,__text,regular,pure_instructions // turbo - This code must reside within the first segment
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// real_to_prot()
//
//
LABEL(__real_to_prot)
.code16
// Interrupts are disabled in protected mode.
cli
// Load the Global Descriptor Table Register (GDTR).
addr32
data32
lgdt OFFSET16(_Gdtr)
lgdtl OFFSET16(_Gdtr)
// Enter protected mode by setting the PE bit in CR0.
mov %cr0, %eax
data32
or $CR0_PE_ON, %eax
or $CR0_PE_ON, %ax
mov %eax, %cr0
// Make intrasegment jump to flush the processor pipeline and
// reload CS register.
data32
ljmp $0x08, $xprot
ljmpl $0x08, $xprot
.code32
xprot:
// we are in USE32 mode now
// set up the protected mode segment registers : DS, SS, ES, FS, GS
mov $0x10, %eax
movw $0x10, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
popl %eax
addl $CODE32_BASE, %eax
pushl %eax
jmp *%eax
ret
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// prot_to_real()
//
ljmp $0x18, $x16 // change to USE16 mode
x16:
.code16
mov %cr0, %eax // clear the PE bit of CR0
data32
and $CR0_PE_OFF, %eax
mov %eax, %cr0
// make intersegment jmp to flush the processor pipeline
// and reload CS register
data32
ljmp $CODE16_SEG, $xreal - CODE32_BASE
ljmp $CODE16_SEG, $xreal
xreal:
// we are in real mode now
// load stack segment register SS.
data32
movl $STACK16_SEG, %eax
movw $STACK16_SEG, %ax
movw %ax, %ss
// clear top 16-bits of ESP and EBP.
data32
movzwl %sp, %esp
data32
movzwl %bp, %ebp
// Modify caller's return address on the stack
// from linear address to segment offset.
data32
popl %eax
data32
movzwl %ax, %eax
data32
pushl %eax
// Reenable maskable interrupts.
sti
data32
ret
jmp *%ax
.code32
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// halt()
//
// Passes arg to the program in %eax.
//
LABEL(_startprog)
push %ebp
mov %esp, %ebp
cli
xor %eax, %eax
mov %eax, _Idtr_prot
movw %ax, _Idtr_prot + 4
lidt _Idtr_prot
mov 0xc(%ebp), %eax // argument to program - bootargs to mach_kernel
mov 0x8(%ebp), %ecx // entry offset
mov $0x28, %ebx // segment
push %ebx
push %ecx
add $4, %esp // discard return address
mov $0x28, %eax // segment
xchg 4(%esp), %eax // argument to program - bootargs to mach_kernel
// set up %ds and %es
mov $0x20, %ebx
movw $0x20, %bx
movw %bx, %ds
movw %bx, %es
// AX, DI, and SI are clobbered.
//
LABEL(__switch_stack)
popl %eax # save return address
popl %edi # discard upper 16-bit
data32
addr32
movl OFFSET16(save_ss), %esi # new SS to SI
.code16
data32
addr32
pop %ax # save return address
pop %di # discard upper 16-bit
movw OFFSET16(save_ss), %si # new SS to SI
movl OFFSET16(save_sp), %edi # new SP to DI
addr32
mov %ss, OFFSET16(save_ss) # save current SS to memory
movw %ss, OFFSET16(save_ss) # save current SS to memory
data32
addr32
movl %esp, OFFSET16(save_sp) # save current SP to memory
cli
mov %si, %ss # switch stack
mov %di, %sp
mov %edi, %esp
sti
pushl %eax # push IP of caller onto the new stack
push %ax # push IP of caller onto the new stack
xorl %eax, %eax
xorl %esi, %esi
xorl %edi, %edi
xor %ax, %ax
xor %si, %si
xor %di, %di
ret
.code32
#ifndef BOOT1
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// loader()
//
LABEL(_loader)
enter $0, $0
pushfl
cli
pushal
#
###### Real Mode Begin ######
data32
call __switch_stack # Switch to NBP stack
.code16
calll __switch_stack # Switch to NBP stack
int $0x2b # Call NBP
data32
call __switch_stack # Restore stack
calll __switch_stack # Restore stack
data32
call __real_to_prot # Back to protected mode
calll __real_to_prot # Back to protected mode
.code32
###### Real Mode End ######
popal
popfl
leave
ret
#endif
branches/zenith432/i386/libsaio/bios.s
3737
3838
3939
40
41
42
4340
4441
4542
......
8077
8178
8279
83
80
8481
85
8682
87
8883
89
9084
91
9285
93
9486
95
9687
97
9888
9989
100
90
10191
10292
10393
......
131121
132122
133123
134
135
136
137
138
124
125
126
139127
140
141
142
128
143129
144130
145131
146
147
148
132
149133
150134
151135
152136
153137
154138
155
156
157
158
159
160
139
140
141
161142
162
163
164
165
143
144
166145
146
147
167148
168149
169150
#include <architecture/i386/asm_help.h>
#include "memory.h"
#define data32 .byte 0x66
#define addr32 .byte 0x67
#define O_INT 0
#define O_EAX 4
#define O_EBX 8
bits of code and data within the first 63.5k and modify the loaders to
be able to load more than 63.5k.
*/
.align 4
.align 2
save_eax: .space 4
.align 4
save_edx: .space 4
.align 2
save_es: .space 2
.align 2
save_flag: .space 2
.align 4
new_eax: .space 4
.align 4
new_edx: .space 4
.align 2
new_es: .space 2
.align 2
new_ds: .space 2
.section __INIT,__text // turbo - This code must reside within the first segment
.section __INIT,__text,regular,pure_instructions // turbo - This code must reside within the first segment
/*============================================================================
call __prot_to_real
data32
addr32
mov OFFSET16(new_eax), %eax
data32
addr32
.code16
mov new_eax, %eax // OFFSET16 not needed due to special opcode for ax/eax
mov OFFSET16(new_edx), %edx
data32
addr32
mov OFFSET16(new_es), %es
movw OFFSET16(new_es), %es
push %ds // Save DS
// Replace DS. WARNING: Don't access data until it's restored!
addr32
data32
mov OFFSET16(new_ds), %ds
movw OFFSET16(new_ds), %ds
do_int:
int $0x00
pop %ds // Restore DS before we do anything else
pushf
data32
addr32
movl %eax, OFFSET16(save_eax)
popl %eax // actually pop %ax
addr32
movl %eax, OFFSET16(save_flag) // actually movw
mov %eax, save_eax
pop %ax
mov %ax, save_flag
mov %es, %ax
addr32
movl %eax, OFFSET16(save_es) // actually movw
data32
call __real_to_prot
mov %ax, save_es
calll __real_to_prot
.code32
movl %edx, new_edx // save new edx before clobbering
movl save_edx, %edx
movl new_edx, %eax // now move it into buffer
branches/zenith432/i386/libsaio/table.c
7070
7171
7272
73
73
7474
7575
7676
};
// turbo - GDT must be in first 64k segment
struct seg_desc __attribute__ ((section("__INIT,__data"))) Gdt[ NGDTENT ] = {
struct seg_desc __attribute__ ((section("__INIT,__data"), aligned(8))) Gdt[ NGDTENT ] = {
/* 0x0 : null */
{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00},
branches/zenith432/i386/libsaio/saio_internal.h
3030
3131
3232
33
34
33
34
3535
3636
3737
/* asm.s */
extern voidreal_to_prot(void);
extern voidprot_to_real(void);
extern voidhalt(void);
extern voidstartprog(unsigned int address, void *arg);
extern voidhalt(void) __attribute__((noreturn));
extern voidstartprog(unsigned int address, void *arg) __attribute__((noreturn));
extern voidloader(UInt32 code, UInt32 cmdptr);
extern uint64_tcomputeRand(void);
branches/zenith432/i386/boot2/mboot.c
4343
4444
4545
46
46
4747
4848
4949
#define FIX_RETURN_ADDRESS_USING_FIRST_ARG(arg) \
RETURN_ADDRESS_USING_FIRST_ARG(arg) -= OFFSET_1MEG
extern void jump_to_chainbooter();
extern void jump_to_chainbooter() __attribute__((noreturn));
extern unsigned char chainbootdev;
extern unsigned char chainbootflag;
branches/zenith432/i386/boot2/boot.c
230230
231231
232232
233
234
235
236
237
238233
239234
240235
......
246241
247242
248243
249
250
251
252
253
254
255244
256245
257246
// Notify modules that the kernel is about to be started
execute_hook("Kernel Start", (void *)kernelEntry, (void *)bootArgs, NULL, NULL);
if (interruptsAvailable)
{
DisableInterrupts();
}
// Masking out so that Lion doesn't doublefault
outb(0x21, 0xff);/* Maskout all interrupts Pic1 */
outb(0xa1, 0xff);/* Maskout all interrupts Pic2 */
// Notify modules that the kernel is about to be started
execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgsPreLion, NULL, NULL);
if (interruptsAvailable)
{
DisableInterrupts();
}
startprog( kernelEntry, bootArgsPreLion );
}
branches/zenith432/i386/boot2/boot2.s
4040
4141
4242
43
44
45
4643
47
44
4845
4946
5047
......
6562
6663
6764
68
69
70
71
72
65
66
67
68
69
70
71
72
7373
7474
7575
......
7777
7878
7979
80
81
80
8281
83
84
82
8583
84
85
8686
8787
8888
......
9696
9797
9898
99
100
101
99
100
101
102
102103
103104
104
105
106
107
108
105
106
107
108
109
109110
110
111
111112
113
114
112115
113116
114117
115118
116119
117120
118
119
120
121
122
123
124
121125
122126
123
124
125
126
127
127
128
129
130
131
128132
129
130133
131134
135
132136
133137
134138
......
153157
154158
155159
156
160
161
162
163
164
157165
158166
159167
......
172180
173181
174182
175
176
177
178
179
183
184
180185
186
187
181188
182189
183190
......
210217
211218
212219
213
220
214221
215222
216223
......
276283
277284
278285
279
286
280287
281288
282289
......
286293
287294
288295
289
296
290297
291298
292299
......
309316
310317
311318
319
320
312321
313322
314323
......
316325
317326
318327
319
320328
321329
330
331
322332
323333
324334
325335
326336
327337
328
338
329339
330340
331
341
332342
333343
334344
......
338348
339349
340350
341
351
342352
343353
344354
345
#include "memory.h"
#include "mboot.h"
#define data32 .byte 0x66
#define retf .byte 0xcb
.file "boot2.s"
.section __INIT,__text// turbo - This initialization code must reside within the first segment
.section __INIT,__text,regular,pure_instructions// turbo - This initialization code must reside within the first segment
//.data
.section __INIT,__data// turbo - Data that must be in the first segment
# Returns:
#
LABEL(boot2) # Entry point at 0:BOOTER_ADDR (will be called by boot1)
pushl %ecx # Save general purpose registers
pushl %ebx
pushl %ebp
pushl %esi
pushl %edi
.code16
push %cx # Save general purpose registers
push %bx
push %bp
push %si
push %di
push %ds # Save DS, ES
push %es
mov %ax, %ds # Set DS and ES to match CS
mov %ax, %es
data32
call __switch_stack # Switch to new stack
calll __switch_stack # Switch to new stack
data32
call __real_to_prot # Enter protected mode.
calll __real_to_prot # Enter protected mode.
.code32
fninit # FPU init
# We are now in 32-bit protected mode.
call __prot_to_real # Back to real mode.
data32
call __switch_stack # Restore original stack
.code16
calll __switch_stack # Restore original stack
pop %es # Restore original ES and DS
pop %ds
popl %edi # Restore all general purpose registers
popl %esi # except EAX.
popl %ebp
popl %ebx
popl %ecx
pop %di # Restore all general purpose registers
pop %si # except AX.
pop %bp
pop %bx
pop %cx
retf # Hardcode a far return
lret # Far return
.code32
start_chain_boot:
xorl %edx, %edx
movb _chainbootdev, %dl # Setup DL with the BIOS device number
call __prot_to_real # Back to real mode.
data32
call __switch_stack # Restore original stack
.code16
calll __switch_stack # Restore original stack
pop %es # Restore original ES and DS
pop %ds
popl %edi # Restore all general purpose registers
popl %esi # except EAX.
popl %ebp
popl %ebx
popl %ecx
pop %di # Restore all general purpose registers
pop %si # except AX.
pop %bp
pop %bx
pop %cx
data32
ljmp $0, $0x7c00 # Jump to boot code already in memory
.code32
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Multiboot support added by David F. Elliott <dfe@cox.net> on 2007/06/26
# cannot do that and have GRUB find it because GRUB only searches the first
# 8k of the binary. Since __TEXT,__const follows __TEXT,__text (the code
# section) and since the code is well over 8k long, it doesn't work.
.align 4, 0x90 # Make sure we're on a 4-byte boundary. Required by Multiboot.
//.data - the entire __INIT segment is less than 1k
.section __INIT,__data// turbo
.align 2 # Make sure we're on a 4-byte boundary. Required by Multiboot.
_multiboot_header:
# magic (NOTE: this shows up as 02b0 ad1b in a hex dump)
.long MULTIBOOT_HEADER_MAGIC
# entry_addr
.long (_multiboot_entry + OFFSET_1MEG)
# Stick a couple of nop here so that we hopefully make disassemblers realize we have instructions again
nop
nop
nop
.align 8, 0x90 # Align to 8 byte boundary which should be enough nops
//.text
.section __INIT,__text// turbo
.align 3, 0x90 # Align to 8 byte boundary
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_multiboot_entry:
# First thing's first, let's get ourselves a usable GDT.
# The desired offset in this case is exactly 1 MB higher than the
# assembler/linker thinks it is. As mentioned above, we use the kernel
# init code selector instead of the boot code selector.
jmp $0x28,$(Lpost_gdt_switch+OFFSET_1MEG)
ljmp $0x28,$(Lpost_gdt_switch+OFFSET_1MEG)
Lpost_gdt_switch:
# Now that we have the right code selector we also want the rest of the
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# _continue_at_low_address does some trickery to get the caller running from the low address with the right selector
.globl _continue_at_low_address
.align 4, 0x90
.align 2, 0x90
_continue_at_low_address:
# Our stack frame has been set up with the return address on top
# First, fix that to be 1 MB lower
lgdt _Gdtr
# Now jump to GDT selector 8 using the low address of this function
# This finally puts us in low memory in the right selector (0x08)
jmpl $0x08,$L_continue_at_low_address_next
ljmp $0x08,$L_continue_at_low_address_next
L_continue_at_low_address_next:
# We don't need to set ss,ds,es,fs, or gs because they are already 0x10
# and the old GDT had the same information for selector 0x10 as the new
call __prot_to_real # Back to real mode.
.code16
# TODO: Set SS:SP to something reasonable? For instance, Microsoft MBR
# code starts out by setting up the stack at 0:7c00 for itself and leaves
# that intact. Thus the stack by default will grow down from the code
# 0:fff0 and it seems that most boot code doesn't care and simply sets
# SS:SP itself as one of the first things it does.
data32
ljmp $0, $0x7c00 # Jump to boot code already in memory
.code32
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# _cause_crash jumps to offset 0 of a selector we know is not in our GDT
# This causes Parallels to output all sorts of nice debugging information
# We aren't using it right now so it's in an if 0 block.
#if 0
.globl _cause_crash
.align 4, 0x90
.align 2, 0x90
_cause_crash:
# Cause a crash, there is no GDT selector f0
jmp $0xf0,$0
ljmp $0xf0,$0
hlt
jmp _cause_crash
#endif
# See the comments above as to why we have OFFSET_1MEG.
//.data
.section __INIT,__data// turbo
.align 4, 0x90
.align 2
_Gdtr_high:
.word GDTLIMIT
.long vtop(_Gdt + OFFSET_1MEG)
branches/zenith432/i386/libsa/interrupts.c
107107
108108
109109
110
110111
111112
112113
......
131132
132133
133134
135
134136
135137
136138
"addl $4, %%esp\n\t"
"iretl"
:);
__builtin_unreachable();
}
static
"addl $8, %%esp\n\t"
"iretl"
:);
__builtin_unreachable();
}
/*

Archive Download the corresponding diff file

Revision: 2597