rev |
line source |
pascal@15368
|
1 /*
|
pascal@15368
|
2 Copyright (C) 2000, Entity Cyber, Inc.
|
pascal@15368
|
3
|
pascal@15368
|
4 Authors: Gary Byers (gb@thinguin.org)
|
pascal@15368
|
5 Marty Connor (mdc@thinguin.org)
|
pascal@15368
|
6
|
pascal@15368
|
7 This software may be used and distributed according to the terms
|
pascal@15368
|
8 of the GNU Public License (GPL), incorporated herein by reference.
|
pascal@15368
|
9
|
pascal@15368
|
10 Description:
|
pascal@15368
|
11
|
pascal@15368
|
12 This is just a little bit of code and data that can get prepended
|
pascal@15368
|
13 to a ROM image in order to allow bootloaders to load the result
|
pascal@15368
|
14 as if it were a Linux kernel image.
|
pascal@15368
|
15
|
pascal@15368
|
16 A real Linux kernel image consists of a one-sector boot loader
|
pascal@15368
|
17 (to load the image from a floppy disk), followed a few sectors
|
pascal@15368
|
18 of setup code, followed by the kernel code itself. There's
|
pascal@15368
|
19 a table in the first sector (starting at offset 497) that indicates
|
pascal@15368
|
20 how many sectors of setup code follow the first sector and which
|
pascal@15368
|
21 contains some other parameters that aren't interesting in this
|
pascal@15368
|
22 case.
|
pascal@15368
|
23
|
pascal@15368
|
24 When a bootloader loads the sectors that comprise a kernel image,
|
pascal@15368
|
25 it doesn't execute the code in the first sector (since that code
|
pascal@15368
|
26 would try to load the image from a floppy disk.) The code in the
|
pascal@15368
|
27 first sector below doesn't expect to get executed (and prints an
|
pascal@15368
|
28 error message if it ever -is- executed.)
|
pascal@15368
|
29
|
pascal@15368
|
30 We don't require much in the way of setup code. Historically, the
|
pascal@15368
|
31 Linux kernel required at least 4 sectors of setup code.
|
pascal@15368
|
32 Therefore, at least 4 sectors must be present even though we don't
|
pascal@15368
|
33 use them.
|
pascal@15368
|
34
|
pascal@15368
|
35 */
|
pascal@15368
|
36
|
pascal@15368
|
37 FILE_LICENCE ( GPL_ANY )
|
pascal@15368
|
38
|
pascal@15368
|
39 #define SETUPSECS 4 /* Minimal nr of setup-sectors */
|
pascal@15368
|
40 #define PREFIXSIZE ((SETUPSECS+1)*512)
|
pascal@15368
|
41 #define PREFIXPGH (PREFIXSIZE / 16 )
|
pascal@15368
|
42 #define BOOTSEG 0x07C0 /* original address of boot-sector */
|
pascal@15368
|
43 #define INITSEG 0x9000 /* we move boot here - out of the way */
|
pascal@15368
|
44 #define SETUPSEG 0x9020 /* setup starts here */
|
pascal@15368
|
45 #define SYSSEG 0x1000 /* system loaded at 0x10000 (65536). */
|
pascal@15368
|
46
|
pascal@15368
|
47 .text
|
pascal@15368
|
48 .code16
|
pascal@15368
|
49 .arch i386
|
pascal@15368
|
50 .org 0
|
pascal@15368
|
51 .section ".prefix", "ax", @progbits
|
pascal@15368
|
52 .globl _lkrn_start
|
pascal@15368
|
53 _lkrn_start:
|
pascal@15368
|
54
|
pascal@15368
|
55 bootsector:
|
pascal@15368
|
56 _start:
|
pascal@15368
|
57
|
pascal@15368
|
58 /* some extra features */
|
pascal@15368
|
59 #define EXE_SUPPORT real mode dos .exe file support
|
pascal@15368
|
60
|
pascal@15368
|
61 #define EXEADRS(x) (x+0xE0)
|
pascal@15368
|
62
|
pascal@15368
|
63 /* some contraints to reduce the size */
|
pascal@15368
|
64 //#define FLOPPY_1440K_ONLY 1.44M floppies support only
|
pascal@15368
|
65
|
pascal@15368
|
66 #ifdef EXE_SUPPORT
|
pascal@15368
|
67 /* Initial temporary stack size */
|
pascal@15368
|
68 #define EXE_STACK_SIZE 0x400
|
pascal@15368
|
69
|
pascal@15368
|
70 /* Temporary decompression area (avoid DOS high memory area) */
|
pascal@15368
|
71 #define EXE_DECOMPRESS_ADDRESS 0x110000
|
pascal@15368
|
72
|
pascal@15368
|
73 /* Fields within the Program Segment Prefix */
|
pascal@15368
|
74 #define PSP_CMDLINE_LEN 0x80
|
pascal@15368
|
75 #define PSP_CMDLINE_START 0x81
|
pascal@15368
|
76
|
pascal@15368
|
77 #define HEADER_SIZE 0x20
|
pascal@15368
|
78
|
pascal@15368
|
79 signature:
|
pascal@15368
|
80 decw %bp // Magic number: MZ
|
pascal@15368
|
81 popw %dx
|
pascal@15368
|
82 jmp start // Bytes on last page of file
|
pascal@15368
|
83 blocks:
|
pascal@15368
|
84 .word 0 // Pages in file
|
pascal@15368
|
85 .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
pascal@15368
|
86 .ascii "ADDW"
|
pascal@15368
|
87 .long blocks
|
pascal@15368
|
88 .long 512
|
pascal@15368
|
89 .long 0
|
pascal@15368
|
90 .previous
|
pascal@15368
|
91 .word 0 // Relocations
|
pascal@15368
|
92 .word ( HEADER_SIZE / 16 ) // Size of header in paragraphs
|
pascal@15368
|
93 .word ( EXE_STACK_SIZE / 16 ) // Minimum extra paragraphs needed
|
pascal@15368
|
94 .word ( EXE_STACK_SIZE / 16 ) // Maximum extra paragraphs needed
|
pascal@15368
|
95 init_ss:
|
pascal@15368
|
96 .word -( ( _exe_start - signature ) / 16 ) // Initial (relative) SS value
|
pascal@15368
|
97 .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
pascal@15368
|
98 .ascii "ADDW"
|
pascal@15368
|
99 .long init_ss
|
pascal@15368
|
100 .long 16
|
pascal@15368
|
101 .long 0
|
pascal@15368
|
102 .previous
|
pascal@15368
|
103 .word EXE_STACK_SIZE // Initial SP value
|
pascal@15368
|
104 .word 0 // Checksum
|
pascal@15368
|
105 .word _exe_start // Initial IP value
|
pascal@15368
|
106 /* Initial code segment (relative to start of executable) */
|
pascal@15368
|
107 //.word -( ( _exe_start - signature ) / 16 ) // Initial (relative) CS value
|
pascal@15368
|
108 .word -( HEADER_SIZE / 16 ) // Initial (relative) CS value
|
pascal@15368
|
109 // .word 0x001C // File address of relocation table
|
pascal@15368
|
110 // .word 0,0,0 // Overlay number
|
pascal@15368
|
111
|
pascal@15368
|
112 start:
|
pascal@15368
|
113 pushw %dx
|
pascal@15368
|
114 xorw %dx, %dx
|
pascal@15368
|
115 #endif
|
pascal@15368
|
116 cld # assume nothing
|
pascal@15368
|
117 stacktop = 0x9E00 # in 0x8000 .. 0xA000
|
pascal@15368
|
118 zeroed = 12 # zeroed registers
|
pascal@15368
|
119 movw $stacktop-12-zeroed, %di # stacktop is an arbitrary value >=
|
pascal@15368
|
120 # length of bootsect + length of
|
pascal@15368
|
121 # setup + room for stack;
|
pascal@15368
|
122 # 12 is disk parm size.
|
pascal@15368
|
123 pushw $INITSEG
|
pascal@15368
|
124 popw %ss # %ss contain INITSEG
|
pascal@15368
|
125 movw %di, %sp # put stack at INITSEG:stacktop-...
|
pascal@15368
|
126
|
pascal@15368
|
127 # Many BIOS's default disk parameter tables will not recognize
|
pascal@15368
|
128 # multi-sector reads beyond the maximum sector number specified
|
pascal@15368
|
129 # in the default diskette parameter tables - this may mean 7
|
pascal@15368
|
130 # sectors in some cases.
|
pascal@15368
|
131 #
|
pascal@15368
|
132 # Since single sector reads are slow and out of the question,
|
pascal@15368
|
133 # we must take care of this by creating new parameter tables
|
pascal@15368
|
134 # (for the first disk) in RAM. We can set the maximum sector
|
pascal@15368
|
135 # count to 36 - the most we will encounter on an ED 2.88.
|
pascal@15368
|
136 #
|
pascal@15368
|
137 # High doesn't hurt. Low does. Let's use the max: 63
|
pascal@15368
|
138
|
pascal@15368
|
139 pushw %ss
|
pascal@15368
|
140 popw %es # %es = %ss = INITSEG
|
pascal@15368
|
141 xorw %ax, %ax # %ax = 0
|
pascal@15368
|
142 movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
|
pascal@15368
|
143 rep # don't worry about cld
|
pascal@15368
|
144 stosw # already done above
|
pascal@15368
|
145 popw %bx # offset = 0
|
pascal@15368
|
146 popw %ds # %ds = 0
|
pascal@15368
|
147 popw %fs # %fs = 0
|
pascal@15368
|
148
|
pascal@15368
|
149 movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0)
|
pascal@15368
|
150 incw %ax
|
pascal@15368
|
151
|
pascal@15368
|
152 ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address
|
pascal@15368
|
153 pushw %es
|
pascal@15368
|
154 pushw %di
|
pascal@15368
|
155 movb $6, %cl # copy 12 bytes
|
pascal@15368
|
156 rep # don't worry about cld
|
pascal@15368
|
157 movsw # already done above
|
pascal@15368
|
158 pushw %ss
|
pascal@15368
|
159 popw %ds # now %ds = %es = %ss = INITSEG
|
pascal@15368
|
160 popl %fs:0x78(%bx) # update parameter table address
|
pascal@15368
|
161 movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
|
pascal@15368
|
162 cli
|
pascal@15368
|
163
|
pascal@15368
|
164 xchg %ax, %di # sector count
|
pascal@15368
|
165 popw %ax # limits = 0
|
pascal@15368
|
166 incw %cx # cylinder 0, sector 1, clear Z
|
pascal@15368
|
167 call read_first_sectors # read setup
|
pascal@15368
|
168
|
pascal@15368
|
169 # This routine loads the system at address LOADSEG, making sure
|
pascal@15368
|
170 # no 64kB boundaries are crossed. We try to load it as fast as
|
pascal@15368
|
171 # possible, loading whole tracks whenever we can.
|
pascal@15368
|
172
|
pascal@15368
|
173 popw %bx # clear %bx
|
pascal@15368
|
174 movw syssize, %di
|
pascal@15368
|
175 addw $(512/16)-1, %di
|
pascal@15368
|
176 shrw $9-4, %di
|
pascal@15368
|
177 movw $SYSSEG, %cx
|
pascal@15368
|
178 call read_sectorsCX
|
pascal@15368
|
179
|
pascal@15368
|
180 # This procedure turns off the floppy drive motor, so
|
pascal@15368
|
181 # that we enter the kernel in a known state, and
|
pascal@15368
|
182 # don't have to worry about it later.
|
pascal@15368
|
183
|
pascal@15368
|
184 kill_motor:
|
pascal@15368
|
185 xchgw %ax, %di # reset FDC (%di < 128)
|
pascal@15368
|
186 int $0x13
|
pascal@15368
|
187
|
pascal@15368
|
188 # After that (everything loaded), we jump to the setup-routine
|
pascal@15368
|
189 # loaded directly after the bootblock:
|
pascal@15368
|
190 # Segments are as follows: %ds = %ss = INITSEG
|
pascal@15368
|
191
|
pascal@15368
|
192 ljmp $SETUPSEG, $0
|
pascal@15368
|
193
|
pascal@15368
|
194 #ifdef EXE_SUPPORT
|
pascal@15368
|
195 dosexit:
|
pascal@15368
|
196 movw $0x4c00, %ax
|
pascal@15368
|
197 int $0x21
|
pascal@15368
|
198
|
pascal@15368
|
199 _exe_start:
|
pascal@15368
|
200 pushw $dosexit
|
pascal@15368
|
201 movw $EXEADRS(need386), %si
|
pascal@15368
|
202 pushfw // save flags
|
pascal@15368
|
203 // bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
pascal@15368
|
204 // flags 0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF
|
pascal@15368
|
205 movb $0x10, %ah // DF = IF = TF = 0
|
pascal@15368
|
206 pushw %ax
|
pascal@15368
|
207 popfw // < 286 : flags[12..15] are forced 1
|
pascal@15368
|
208 pushfw // = 286 : flags[12..15] are forced 0
|
pascal@15368
|
209 popw %cx // > 286 : only flags[15] is forced 0
|
pascal@15368
|
210 popfw // restore flags
|
pascal@15368
|
211 addb %ah, %ch // test F0 and 00 cases
|
pascal@15368
|
212 cmpb %ah, %ch
|
pascal@15368
|
213 jbe puts // C=8086/80186, Z=80286
|
pascal@15368
|
214 // smsww %ax
|
pascal@15368
|
215 // andb $1, %al
|
pascal@15368
|
216 // jne puts
|
pascal@15368
|
217
|
pascal@15368
|
218 /* Terminate command line with a NUL */
|
pascal@15368
|
219 movzbw PSP_CMDLINE_LEN, %si
|
pascal@15368
|
220 movb $0, PSP_CMDLINE_START(%si)
|
pascal@15368
|
221 cmpb $'?', PSP_CMDLINE_START-1(%si)
|
pascal@15368
|
222 je help
|
pascal@15368
|
223 pushw %si
|
pascal@15368
|
224
|
pascal@15368
|
225 /* Install iPXE. Use a fixed temporary decompression area to
|
pascal@15368
|
226 * avoid trashing the DOS high memory area.
|
pascal@15368
|
227 */
|
pascal@15368
|
228 call alloc_basemem
|
pascal@15368
|
229 movl $EXE_DECOMPRESS_ADDRESS, %edi
|
pascal@15368
|
230 stc
|
pascal@15368
|
231 sbbl %ebp, %ebp /* Allow arbitrary relocation */
|
pascal@15368
|
232 xorl %esi, %esi
|
pascal@15368
|
233 call install_prealloc
|
pascal@15368
|
234
|
pascal@15368
|
235 xorl %ebp, %ebp
|
pascal@15368
|
236 xorl %ecx, %ecx
|
pascal@15368
|
237
|
pascal@15368
|
238 /* Calculate command line physical address */
|
pascal@15368
|
239 xorl %edx, %edx
|
pascal@15368
|
240 movw %ds, %dx
|
pascal@15368
|
241 shll $4, %edx
|
pascal@15368
|
242 popw %si
|
pascal@15368
|
243 orw %si, %si
|
pascal@15368
|
244 jne gotarg
|
pascal@15368
|
245 movw $EXEADRS(default_config), %bp
|
pascal@15368
|
246 addl %edx, %ebp
|
pascal@15368
|
247 movw $0xA00-default_config, %cx
|
pascal@15368
|
248 gotarg:
|
pascal@15368
|
249 addl $PSP_CMDLINE_START, %edx
|
pascal@15368
|
250
|
pascal@15368
|
251 jmp start_ipxe
|
pascal@15368
|
252
|
pascal@15368
|
253 help:
|
pascal@15368
|
254 movw $EXEADRS(helpmsg), %si
|
pascal@15368
|
255 puts:
|
pascal@15368
|
256 lodsb
|
pascal@15368
|
257 orb %al, %al
|
pascal@15368
|
258 je exit
|
pascal@15368
|
259 call putc
|
pascal@15368
|
260 jmp puts
|
pascal@15368
|
261 #endif
|
pascal@15368
|
262
|
pascal@15368
|
263 putcdot:
|
pascal@15368
|
264 movb $0x2E, %al
|
pascal@15368
|
265 putc:
|
pascal@15368
|
266 movb $0xE, %ah
|
pascal@15368
|
267 movw $7, %bx
|
pascal@15368
|
268 int $0x10
|
pascal@15368
|
269 exit:
|
pascal@15368
|
270 ret
|
pascal@15368
|
271
|
pascal@15368
|
272
|
pascal@15368
|
273 # read_sectors reads %di sectors into %es:0 buffer.
|
pascal@15368
|
274 # %es:0 is updated to the next memory location.
|
pascal@15368
|
275 # First, sectors are read sector by sector until
|
pascal@15368
|
276 # sector per track count is known. Then they are
|
pascal@15368
|
277 # read track by track.
|
pascal@15368
|
278 # Assume no error on first track.
|
pascal@15368
|
279
|
pascal@15368
|
280 #ifdef FLOPPY_1440K_ONLY
|
pascal@15368
|
281 #define FLOPPY_HEADS 2 /* 2 heads */
|
pascal@15368
|
282 #define FLOPPY_SECTORS 18 /* 18 sectors */
|
pascal@15368
|
283 #else
|
pascal@15368
|
284 #define FLOPPY_HEADS 2 /* 2 heads minimum */
|
pascal@15368
|
285 #define FLOPPY_SECTORS 9 /* 9 sectors minimum */
|
pascal@15368
|
286 #endif
|
pascal@15368
|
287
|
pascal@15368
|
288 check_limits:
|
pascal@15368
|
289 #ifndef FLOPPY_1440K_ONLY
|
pascal@15368
|
290 popw %dx
|
pascal@15368
|
291 #ifdef FLOPPY_SECTORS
|
pascal@15368
|
292 cmpb $FLOPPY_SECTORS+1, %cl # minimum sector count
|
pascal@15368
|
293 jb check_head
|
pascal@15368
|
294 #endif
|
pascal@15368
|
295 cmpb %al, %cl # max sector known ?
|
pascal@15368
|
296 ja next_head # no -> store it
|
pascal@15368
|
297 check_head:
|
pascal@15368
|
298 #ifdef FLOPPY_HEADS
|
pascal@15368
|
299 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
|
pascal@15368
|
300 jb check_cylinder
|
pascal@15368
|
301 #endif
|
pascal@15368
|
302 cmpb %ah, %dh # max head known ?
|
pascal@15368
|
303 ja next_cylinder # no -> store it
|
pascal@15368
|
304 check_cylinder:
|
pascal@15368
|
305 #endif
|
pascal@15368
|
306 pushaw
|
pascal@15368
|
307 #ifndef FLOPPY_1440K_ONLY
|
pascal@15368
|
308 cbw # %ah = 0
|
pascal@15368
|
309 #endif
|
pascal@15368
|
310 int $0x13 # reset controler
|
pascal@15368
|
311 popaw
|
pascal@15368
|
312 movb $1, %al # sector by sector...
|
pascal@15368
|
313 read_sectorslp:
|
pascal@15368
|
314 pushw %dx # some bios break dx...
|
pascal@15368
|
315 #ifndef FLOPPY_1440K_ONLY
|
pascal@15368
|
316 pushw %ax # limits
|
pascal@15368
|
317 subb %cl, %al # sectors remaining in track
|
pascal@15368
|
318 ja tolastsect
|
pascal@15368
|
319 movb $1, %al # 1 sector mini
|
pascal@15368
|
320 tolastsect:
|
pascal@15368
|
321 #else
|
pascal@15368
|
322 mov $FLOPPY_SECTORS+1, %al
|
pascal@15368
|
323 subb %cl, %al # sectors remaining in track
|
pascal@15368
|
324 #endif
|
pascal@15368
|
325 cbw
|
pascal@15368
|
326 cmpw %di, %ax
|
pascal@15368
|
327 jb more1trk
|
pascal@15368
|
328 movw %di, %ax # sectors to read
|
pascal@15368
|
329 more1trk:
|
pascal@15368
|
330 pushw %ax # save context
|
pascal@15368
|
331 movb $2, %ah # cmd: read chs
|
pascal@15368
|
332 int $0x13
|
pascal@15368
|
333 #ifndef FLOPPY_1440K_ONLY
|
pascal@15368
|
334 popw %dx # save %ax
|
pascal@15368
|
335 popw %ax # limits
|
pascal@15368
|
336 #else
|
pascal@15368
|
337 popw %ax # restore context
|
pascal@15368
|
338 popw %dx
|
pascal@15368
|
339 #endif
|
pascal@15368
|
340 jc check_limits
|
pascal@15368
|
341 #ifndef FLOPPY_1440K_ONLY
|
pascal@15368
|
342 xchgw %ax, %bp
|
pascal@15368
|
343 addw %dx,%cx # next sector
|
pascal@15368
|
344 movw %cx, %gs
|
pascal@15368
|
345 movw %es, %cx
|
pascal@15368
|
346 pushw %dx
|
pascal@15368
|
347 shlw $5, %dx
|
pascal@15368
|
348 addw %dx, %cx
|
pascal@15368
|
349 popw %dx
|
pascal@15368
|
350 subw %dx,%di # update sector counter
|
pascal@15368
|
351 popw %dx
|
pascal@15368
|
352 read_sectorsCX:
|
pascal@15368
|
353 movw %cx, %es # next location
|
pascal@15368
|
354 jz putcdot
|
pascal@15368
|
355 #else
|
pascal@15368
|
356 addw %ax,%cx # next sector
|
pascal@15368
|
357 movw %cx, %gs
|
pascal@15368
|
358 movw %es, %cx
|
pascal@15368
|
359 pushw %ax
|
pascal@15368
|
360 shlw $5, %ax
|
pascal@15368
|
361 addw %ax, %cx
|
pascal@15368
|
362 popw %ax
|
pascal@15368
|
363 subw %ax,%di # update sector counter
|
pascal@15368
|
364 read_sectorsCX:
|
pascal@15368
|
365 movw %cx, %es # next location
|
pascal@15368
|
366 jz putcdot
|
pascal@15368
|
367 #endif
|
pascal@15368
|
368 read_sectors:
|
pascal@15368
|
369 movw %gs, %cx
|
pascal@15368
|
370 #ifndef FLOPPY_1440K_ONLY
|
pascal@15368
|
371 # al is last sector+1
|
pascal@15368
|
372 # ah is last cylinder+1
|
pascal@15368
|
373 xchgw %ax, %bp
|
pascal@15368
|
374 #endif
|
pascal@15368
|
375 #ifndef FLOPPY_1440K_ONLY
|
pascal@15368
|
376 cmpb %al,%cl # reach sector limit ?
|
pascal@15368
|
377 jne bdendlp
|
pascal@15368
|
378 next_head:
|
pascal@15368
|
379 movb %cl,%al
|
pascal@15368
|
380 #else
|
pascal@15368
|
381 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
|
pascal@15368
|
382 jne bdendlp
|
pascal@15368
|
383 #endif
|
pascal@15368
|
384 incb %dh # next head
|
pascal@15368
|
385 movb $1,%cl # first sector
|
pascal@15368
|
386 #ifndef FLOPPY_1440K_ONLY
|
pascal@15368
|
387 cmpb %ah, %dh # reach head limit ?
|
pascal@15368
|
388 jne bdendlp
|
pascal@15368
|
389 next_cylinder:
|
pascal@15368
|
390 movb %dh,%ah
|
pascal@15368
|
391 #else
|
pascal@15368
|
392 cmpb %cl,%dh # reach head limit ?
|
pascal@15368
|
393 je bdendlp
|
pascal@15368
|
394 #endif
|
pascal@15368
|
395 # NOTE : support 256 cylinders max
|
pascal@15368
|
396 incb %ch # next cylinder
|
pascal@15368
|
397 read_first_sectors:
|
pascal@15368
|
398 movb $0,%dh # first head
|
pascal@15368
|
399 bdendlp:
|
pascal@15368
|
400 jmp read_sectorslp
|
pascal@15368
|
401
|
pascal@15368
|
402 #ifdef EXE_SUPPORT
|
pascal@15368
|
403 need386:
|
pascal@15368
|
404 .ascii "No 386+."
|
pascal@15368
|
405 .byte 13,10
|
pascal@15368
|
406 .byte 0
|
pascal@15368
|
407 helpmsg:
|
pascal@15368
|
408 .ascii "No help available."
|
pascal@15368
|
409 .byte 13,10
|
pascal@15368
|
410 .byte 0
|
pascal@15368
|
411 #endif
|
pascal@15368
|
412
|
pascal@15368
|
413 /*
|
pascal@15368
|
414 The following header is documented in the Linux source code at
|
pascal@15368
|
415 Documentation/x86/boot.txt
|
pascal@15368
|
416 */
|
pascal@15368
|
417 .org 497
|
pascal@15368
|
418 setup_sects:
|
pascal@15368
|
419 .byte SETUPSECS
|
pascal@15368
|
420 root_flags:
|
pascal@15368
|
421 .word 0
|
pascal@15368
|
422 syssize:
|
pascal@15368
|
423 .long -PREFIXPGH
|
pascal@15368
|
424
|
pascal@15368
|
425 .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
pascal@15368
|
426 .ascii "ADDL"
|
pascal@15368
|
427 .long syssize
|
pascal@15368
|
428 .long 16
|
pascal@15368
|
429 .long 0
|
pascal@15368
|
430 .previous
|
pascal@15368
|
431
|
pascal@15368
|
432 ram_size:
|
pascal@15368
|
433 .word 0
|
pascal@15368
|
434 vid_mode:
|
pascal@15368
|
435 .word 0
|
pascal@15368
|
436 root_dev:
|
pascal@15368
|
437 .word 0
|
pascal@15368
|
438 boot_flag:
|
pascal@15368
|
439 .word 0xAA55
|
pascal@15368
|
440 jump:
|
pascal@15368
|
441 /* Manually specify a two-byte jmp instruction here rather
|
pascal@15368
|
442 * than leaving it up to the assembler. */
|
pascal@15368
|
443 .byte 0xeb
|
pascal@15368
|
444 .byte setup_code - header
|
pascal@15368
|
445 header:
|
pascal@15368
|
446 .byte 'H', 'd', 'r', 'S'
|
pascal@15368
|
447 version:
|
pascal@15368
|
448 .word 0x0207 /* 2.07 */
|
pascal@15368
|
449 realmode_swtch:
|
pascal@15368
|
450 .long 0
|
pascal@15368
|
451 start_sys:
|
pascal@15368
|
452 .word 0
|
pascal@15368
|
453 kernel_version:
|
pascal@15368
|
454 .word 0
|
pascal@15368
|
455 type_of_loader:
|
pascal@15368
|
456 .byte 0
|
pascal@15368
|
457 loadflags:
|
pascal@15368
|
458 .byte 0
|
pascal@15368
|
459 setup_move_size:
|
pascal@15368
|
460 .word 0
|
pascal@15368
|
461 code32_start:
|
pascal@15368
|
462 .long SYSSEG*16
|
pascal@15368
|
463 ramdisk_image:
|
pascal@15368
|
464 .long 0
|
pascal@15368
|
465 ramdisk_size:
|
pascal@15368
|
466 .long 0
|
pascal@15368
|
467 bootsect_kludge:
|
pascal@15368
|
468 .long 0
|
pascal@15368
|
469 heap_end_ptr:
|
pascal@15368
|
470 .word 0
|
pascal@15368
|
471 pad1:
|
pascal@15368
|
472 .word 0
|
pascal@15368
|
473 cmd_line_ptr:
|
pascal@15368
|
474 .long 0
|
pascal@15368
|
475 initrd_addr_max:
|
pascal@15368
|
476 /* We don't use an initrd but some bootloaders (e.g. SYSLINUX) have
|
pascal@15368
|
477 * been known to require this field. Set the value to 2 GB. This
|
pascal@15368
|
478 * value is also used by the Linux kernel. */
|
pascal@15368
|
479 .long 0x7fffffff
|
pascal@15368
|
480 kernel_alignment:
|
pascal@15368
|
481 .long 0
|
pascal@15368
|
482 relocatable_kernel:
|
pascal@15368
|
483 .byte 0
|
pascal@15368
|
484 pad2:
|
pascal@15368
|
485 .byte 0, 0, 0
|
pascal@15368
|
486 cmdline_size:
|
pascal@15368
|
487 .long 0x7ff
|
pascal@15368
|
488 hardware_subarch:
|
pascal@15368
|
489 .long 0
|
pascal@15368
|
490 hardware_subarch_data:
|
pascal@15368
|
491 .byte 0, 0, 0, 0, 0, 0, 0, 0
|
pascal@15368
|
492
|
pascal@15368
|
493 /*
|
pascal@15368
|
494 We don't need to do too much setup.
|
pascal@15368
|
495
|
pascal@15368
|
496 This code gets loaded at SETUPSEG:0. It wants to start
|
pascal@15368
|
497 executing the image that's loaded at SYSSEG:0 and
|
pascal@15368
|
498 whose entry point is SYSSEG:0.
|
pascal@15368
|
499 */
|
pascal@15368
|
500 setup_code:
|
pascal@15368
|
501 movl ramdisk_image, %eax
|
pascal@15368
|
502 orl %eax, %eax
|
pascal@15368
|
503 jnz setup_done
|
pascal@15368
|
504
|
pascal@15368
|
505 movw $default_config, %di
|
pascal@15368
|
506 movw $-1, %bx
|
pascal@15368
|
507
|
pascal@15368
|
508 movw $9, %cx
|
pascal@15368
|
509 1:
|
pascal@15368
|
510 pushw %ax
|
pascal@15368
|
511 loop 1b
|
pascal@15368
|
512 pushw $0x9310
|
pascal@15368
|
513 pushw %ax
|
pascal@15368
|
514 pushw %bx
|
pascal@15368
|
515 pushw %ax
|
pascal@15368
|
516 pushw $0x9300+(INITSEG>>12)
|
pascal@15368
|
517 pushw %di
|
pascal@15368
|
518 pushw %bx
|
pascal@15368
|
519 movb $8, %cl
|
pascal@15368
|
520 1:
|
pascal@15368
|
521 pushw %ax
|
pascal@15368
|
522 loop 1b
|
pascal@15368
|
523 1:
|
pascal@15368
|
524 incw %bx
|
pascal@15368
|
525 cmpb %al, (%bx,%di)
|
pascal@15368
|
526 jne 1b
|
pascal@15368
|
527 movw %bx, ramdisk_size
|
pascal@15368
|
528 movb $0x10, ramdisk_image+2
|
pascal@15368
|
529
|
pascal@15368
|
530 pushw %ss
|
pascal@15368
|
531 popw %es
|
pascal@15368
|
532 movw %sp, %si
|
pascal@15368
|
533 movb $0x87, %ah
|
pascal@15368
|
534 movw $(run_ipxe-default_config)/2+1, %cx
|
pascal@15368
|
535 int $0x15
|
pascal@15368
|
536
|
pascal@15368
|
537 setup_done:
|
pascal@15368
|
538 /* We expect to be contiguous in memory once loaded. The Linux image
|
pascal@15368
|
539 * boot process requires that setup code is loaded separately from
|
pascal@15368
|
540 * "non-real code". Since we don't need any information that's left
|
pascal@15368
|
541 * in the prefix, it doesn't matter: we just have to ensure that
|
pascal@15368
|
542 * %cs:0000 is where the start of the image *would* be.
|
pascal@15368
|
543 */
|
pascal@15368
|
544 ljmp $(SYSSEG-(PREFIXSIZE/16)), $run_ipxe
|
pascal@15368
|
545
|
pascal@15368
|
546 default_config:
|
pascal@15368
|
547
|
pascal@15368
|
548 .org PREFIXSIZE
|
pascal@15368
|
549 /*
|
pascal@15368
|
550 We're now at the beginning of the kernel proper.
|
pascal@15368
|
551 */
|
pascal@15368
|
552 run_ipxe:
|
pascal@15368
|
553 /* Set up stack just below 0x7c00 and clear direction flag */
|
pascal@15368
|
554 xorw %ax, %ax
|
pascal@15368
|
555 movw %ax, %ss
|
pascal@15368
|
556 movw $0x7c00, %sp
|
pascal@15368
|
557 cld
|
pascal@15368
|
558
|
pascal@15368
|
559 /* Retrieve command-line pointer */
|
pascal@15368
|
560 movl %ds:cmd_line_ptr, %edx
|
pascal@15368
|
561 testl %edx, %edx
|
pascal@15368
|
562 jz no_cmd_line
|
pascal@15368
|
563
|
pascal@15368
|
564 /* Set up %es:%di to point to command line */
|
pascal@15368
|
565 movl %edx, %edi
|
pascal@15368
|
566 andl $0xf, %edi
|
pascal@15368
|
567 rorl $4, %edx
|
pascal@15368
|
568 movw %dx, %es
|
pascal@15368
|
569
|
pascal@15368
|
570 /* Find length of command line */
|
pascal@15368
|
571 pushw %di
|
pascal@15368
|
572 movw $0xffff, %cx
|
pascal@15368
|
573 repnz scasb
|
pascal@15368
|
574 notw %cx
|
pascal@15368
|
575 popw %si
|
pascal@15368
|
576
|
pascal@15368
|
577 /* Make space for command line on stack */
|
pascal@15368
|
578 movw %sp, %di
|
pascal@15368
|
579 subw %cx, %di
|
pascal@15368
|
580 andw $~0xf, %di
|
pascal@15368
|
581 movw %di, %sp
|
pascal@15368
|
582
|
pascal@15368
|
583 /* Copy command line to stack */
|
pascal@15368
|
584 pushw %ds
|
pascal@15368
|
585 pushw %es
|
pascal@15368
|
586 popw %ds
|
pascal@15368
|
587 pushw %ss
|
pascal@15368
|
588 popw %es
|
pascal@15368
|
589 rep movsb
|
pascal@15368
|
590 popw %ds
|
pascal@15368
|
591
|
pascal@15368
|
592 /* Store new command-line pointer */
|
pascal@15368
|
593 movzwl %sp, %edx
|
pascal@15368
|
594 no_cmd_line:
|
pascal@15368
|
595
|
pascal@15368
|
596 /* Calculate maximum relocation address */
|
pascal@15368
|
597 movl ramdisk_image, %ebp
|
pascal@15368
|
598 testl %ebp, %ebp
|
pascal@15368
|
599 jnz 1f
|
pascal@15368
|
600 decl %ebp /* Allow arbitrary relocation if no initrd */
|
pascal@15368
|
601 1:
|
pascal@15368
|
602
|
pascal@15368
|
603 /* Install iPXE */
|
pascal@15368
|
604 call alloc_basemem
|
pascal@15368
|
605 xorl %esi, %esi
|
pascal@15368
|
606 xorl %edi, %edi
|
pascal@15368
|
607 call install_prealloc
|
pascal@15368
|
608
|
pascal@15368
|
609 /* Retrieve initrd pointer and size */
|
pascal@15368
|
610 movl ramdisk_image, %ebp
|
pascal@15368
|
611 movl ramdisk_size, %ecx
|
pascal@15368
|
612
|
pascal@15368
|
613 start_ipxe:
|
pascal@15368
|
614 /* Set up real-mode stack */
|
pascal@15368
|
615 movw %bx, %ss
|
pascal@15368
|
616 movw $_estack16, %sp
|
pascal@15368
|
617
|
pascal@15368
|
618 /* Jump to .text16 segment */
|
pascal@15368
|
619 pushw %ax
|
pascal@15368
|
620 pushw $1f
|
pascal@15368
|
621 lret
|
pascal@15368
|
622 .section ".text16", "awx", @progbits
|
pascal@15368
|
623 1:
|
pascal@15368
|
624 /* Set up %ds for access to .data16 */
|
pascal@15368
|
625 movw %bx, %ds
|
pascal@15368
|
626
|
pascal@15368
|
627 /* Store command-line pointer */
|
pascal@15368
|
628 movl %edx, cmdline_phys
|
pascal@15368
|
629
|
pascal@15368
|
630 /* Store initrd pointer and size */
|
pascal@15368
|
631 movl %ebp, initrd_phys
|
pascal@15368
|
632 movl %ecx, initrd_len
|
pascal@15368
|
633
|
pascal@15368
|
634 /* Run iPXE */
|
pascal@15368
|
635 pushl $main
|
pascal@15368
|
636 pushw %cs
|
pascal@15368
|
637 call prot_call
|
pascal@15368
|
638 popl %ecx /* discard */
|
pascal@15368
|
639
|
pascal@15368
|
640 /* Uninstall iPXE */
|
pascal@15368
|
641 call uninstall
|
pascal@15368
|
642
|
pascal@15368
|
643 /* Boot next device */
|
pascal@15368
|
644 int $0x18
|