diff options
author | H. Peter Anvin <hpa@zytor.com> | 2007-05-08 23:37:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 23:47:51 -0400 |
commit | de372ecd80a42c4fb485c7232475301a18d05184 (patch) | |
tree | e8707521df8b4d2ea97a8b2fed33a49721cd151a /Documentation/i386 | |
parent | d5f9f942c601fdebe57f7805e4b4fbad9c28ada8 (diff) |
Documentation/i386/boot.txt: update and correct
In the process of rewriting the x86 setup code, I found a number of
inaccuracies and outdated recommendations in the boot protocol
documentation. Revamp to make it more up to date.
In particular, the common use of the heap actually requires (slightly)
more than 4K of heap plus stack, which is the recommended amount in
the document; currently the code compensates by being smaller than
specified, but we can't assume that will be true forever. Thus,
recommend that if we have a modern bzImage kernel, that the bootloader
maximizes the available space.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'Documentation/i386')
-rw-r--r-- | Documentation/i386/boot.txt | 101 |
1 files changed, 78 insertions, 23 deletions
diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt index 6498666ea330..d01b7a2a0f2e 100644 --- a/Documentation/i386/boot.txt +++ b/Documentation/i386/boot.txt | |||
@@ -2,7 +2,7 @@ | |||
2 | ---------------------------- | 2 | ---------------------------- |
3 | 3 | ||
4 | H. Peter Anvin <hpa@zytor.com> | 4 | H. Peter Anvin <hpa@zytor.com> |
5 | Last update 2007-03-06 | 5 | Last update 2007-05-07 |
6 | 6 | ||
7 | On the i386 platform, the Linux kernel uses a rather complicated boot | 7 | On the i386 platform, the Linux kernel uses a rather complicated boot |
8 | convention. This has evolved partially due to historical aspects, as | 8 | convention. This has evolved partially due to historical aspects, as |
@@ -11,7 +11,7 @@ bootable image, the complicated PC memory model and due to changed | |||
11 | expectations in the PC industry caused by the effective demise of | 11 | expectations in the PC industry caused by the effective demise of |
12 | real-mode DOS as a mainstream operating system. | 12 | real-mode DOS as a mainstream operating system. |
13 | 13 | ||
14 | Currently, four versions of the Linux/i386 boot protocol exist. | 14 | Currently, the following versions of the Linux/i386 boot protocol exist. |
15 | 15 | ||
16 | Old kernels: zImage/Image support only. Some very early kernels | 16 | Old kernels: zImage/Image support only. Some very early kernels |
17 | may not even support a command line. | 17 | may not even support a command line. |
@@ -183,9 +183,9 @@ filled out, however: | |||
183 | a version number. Otherwise, enter 0xFF here. | 183 | a version number. Otherwise, enter 0xFF here. |
184 | 184 | ||
185 | Assigned boot loader ids: | 185 | Assigned boot loader ids: |
186 | 0 LILO | 186 | 0 LILO (0x00 reserved for pre-2.00 bootloader) |
187 | 1 Loadlin | 187 | 1 Loadlin |
188 | 2 bootsect-loader | 188 | 2 bootsect-loader (0x20, all other values reserved) |
189 | 3 SYSLINUX | 189 | 3 SYSLINUX |
190 | 4 EtherBoot | 190 | 4 EtherBoot |
191 | 5 ELILO | 191 | 5 ELILO |
@@ -210,6 +210,9 @@ filled out, however: | |||
210 | additional data (such as the kernel command line) moved in | 210 | additional data (such as the kernel command line) moved in |
211 | addition to the real-mode kernel itself. | 211 | addition to the real-mode kernel itself. |
212 | 212 | ||
213 | The unit is bytes starting with the beginning of the boot | ||
214 | sector. | ||
215 | |||
213 | ramdisk_image, ramdisk_size: | 216 | ramdisk_image, ramdisk_size: |
214 | If your boot loader has loaded an initial ramdisk (initrd), | 217 | If your boot loader has loaded an initial ramdisk (initrd), |
215 | set ramdisk_image to the 32-bit pointer to the ramdisk data | 218 | set ramdisk_image to the 32-bit pointer to the ramdisk data |
@@ -278,14 +281,54 @@ command line is entered using the following protocol: | |||
278 | field. | 281 | field. |
279 | 282 | ||
280 | 283 | ||
284 | **** MEMORY LAYOUT OF THE REAL-MODE CODE | ||
285 | |||
286 | The real-mode code requires a stack/heap to be set up, as well as | ||
287 | memory allocated for the kernel command line. This needs to be done | ||
288 | in the real-mode accessible memory in bottom megabyte. | ||
289 | |||
290 | It should be noted that modern machines often have a sizable Extended | ||
291 | BIOS Data Area (EBDA). As a result, it is advisable to use as little | ||
292 | of the low megabyte as possible. | ||
293 | |||
294 | Unfortunately, under the following circumstances the 0x90000 memory | ||
295 | segment has to be used: | ||
296 | |||
297 | - When loading a zImage kernel ((loadflags & 0x01) == 0). | ||
298 | - When loading a 2.01 or earlier boot protocol kernel. | ||
299 | |||
300 | -> For the 2.00 and 2.01 boot protocols, the real-mode code | ||
301 | can be loaded at another address, but it is internally | ||
302 | relocated to 0x90000. For the "old" protocol, the | ||
303 | real-mode code must be loaded at 0x90000. | ||
304 | |||
305 | When loading at 0x90000, avoid using memory above 0x9a000. | ||
306 | |||
307 | For boot protocol 2.02 or higher, the command line does not have to be | ||
308 | located in the same 64K segment as the real-mode setup code; it is | ||
309 | thus permitted to give the stack/heap the full 64K segment and locate | ||
310 | the command line above it. | ||
311 | |||
312 | The kernel command line should not be located below the real-mode | ||
313 | code, nor should it be located in high memory. | ||
314 | |||
315 | |||
281 | **** SAMPLE BOOT CONFIGURATION | 316 | **** SAMPLE BOOT CONFIGURATION |
282 | 317 | ||
283 | As a sample configuration, assume the following layout of the real | 318 | As a sample configuration, assume the following layout of the real |
284 | mode segment (this is a typical, and recommended layout): | 319 | mode segment: |
320 | |||
321 | When loading below 0x90000, use the entire segment: | ||
322 | |||
323 | 0x0000-0x7fff Real mode kernel | ||
324 | 0x8000-0xdfff Stack and heap | ||
325 | 0xe000-0xffff Kernel command line | ||
285 | 326 | ||
286 | 0x0000-0x7FFF Real mode kernel | 327 | When loading at 0x90000 OR the protocol version is 2.01 or earlier: |
287 | 0x8000-0x8FFF Stack and heap | 328 | |
288 | 0x9000-0x90FF Kernel command line | 329 | 0x0000-0x7fff Real mode kernel |
330 | 0x8000-0x97ff Stack and heap | ||
331 | 0x9800-0x9fff Kernel command line | ||
289 | 332 | ||
290 | Such a boot loader should enter the following fields in the header: | 333 | Such a boot loader should enter the following fields in the header: |
291 | 334 | ||
@@ -301,22 +344,33 @@ Such a boot loader should enter the following fields in the header: | |||
301 | ramdisk_image = <initrd_address>; | 344 | ramdisk_image = <initrd_address>; |
302 | ramdisk_size = <initrd_size>; | 345 | ramdisk_size = <initrd_size>; |
303 | } | 346 | } |
347 | |||
348 | if ( protocol >= 0x0202 && loadflags & 0x01 ) | ||
349 | heap_end = 0xe000; | ||
350 | else | ||
351 | heap_end = 0x9800; | ||
352 | |||
304 | if ( protocol >= 0x0201 ) { | 353 | if ( protocol >= 0x0201 ) { |
305 | heap_end_ptr = 0x9000 - 0x200; | 354 | heap_end_ptr = heap_end - 0x200; |
306 | loadflags |= 0x80; /* CAN_USE_HEAP */ | 355 | loadflags |= 0x80; /* CAN_USE_HEAP */ |
307 | } | 356 | } |
357 | |||
308 | if ( protocol >= 0x0202 ) { | 358 | if ( protocol >= 0x0202 ) { |
309 | cmd_line_ptr = base_ptr + 0x9000; | 359 | cmd_line_ptr = base_ptr + heap_end; |
360 | strcpy(cmd_line_ptr, cmdline); | ||
310 | } else { | 361 | } else { |
311 | cmd_line_magic = 0xA33F; | 362 | cmd_line_magic = 0xA33F; |
312 | cmd_line_offset = 0x9000; | 363 | cmd_line_offset = heap_end; |
313 | setup_move_size = 0x9100; | 364 | setup_move_size = heap_end + strlen(cmdline)+1; |
365 | strcpy(base_ptr+cmd_line_offset, cmdline); | ||
314 | } | 366 | } |
315 | } else { | 367 | } else { |
316 | /* Very old kernel */ | 368 | /* Very old kernel */ |
317 | 369 | ||
370 | heap_end = 0x9800; | ||
371 | |||
318 | cmd_line_magic = 0xA33F; | 372 | cmd_line_magic = 0xA33F; |
319 | cmd_line_offset = 0x9000; | 373 | cmd_line_offset = heap_end; |
320 | 374 | ||
321 | /* A very old kernel MUST have its real-mode code | 375 | /* A very old kernel MUST have its real-mode code |
322 | loaded at 0x90000 */ | 376 | loaded at 0x90000 */ |
@@ -324,12 +378,11 @@ Such a boot loader should enter the following fields in the header: | |||
324 | if ( base_ptr != 0x90000 ) { | 378 | if ( base_ptr != 0x90000 ) { |
325 | /* Copy the real-mode kernel */ | 379 | /* Copy the real-mode kernel */ |
326 | memcpy(0x90000, base_ptr, (setup_sects+1)*512); | 380 | memcpy(0x90000, base_ptr, (setup_sects+1)*512); |
327 | /* Copy the command line */ | ||
328 | memcpy(0x99000, base_ptr+0x9000, 256); | ||
329 | |||
330 | base_ptr = 0x90000; /* Relocated */ | 381 | base_ptr = 0x90000; /* Relocated */ |
331 | } | 382 | } |
332 | 383 | ||
384 | strcpy(0x90000+cmd_line_offset, cmdline); | ||
385 | |||
333 | /* It is recommended to clear memory up to the 32K mark */ | 386 | /* It is recommended to clear memory up to the 32K mark */ |
334 | memset(0x90000 + (setup_sects+1)*512, 0, | 387 | memset(0x90000 + (setup_sects+1)*512, 0, |
335 | (64-(setup_sects+1))*512); | 388 | (64-(setup_sects+1))*512); |
@@ -375,10 +428,11 @@ conflict with actual kernel options now or in the future. | |||
375 | line is parsed. | 428 | line is parsed. |
376 | 429 | ||
377 | mem=<size> | 430 | mem=<size> |
378 | <size> is an integer in C notation optionally followed by K, M | 431 | <size> is an integer in C notation optionally followed by |
379 | or G (meaning << 10, << 20 or << 30). This specifies the end | 432 | (case insensitive) K, M, G, T, P or E (meaning << 10, << 20, |
380 | of memory to the kernel. This affects the possible placement | 433 | << 30, << 40, << 50 or << 60). This specifies the end of |
381 | of an initrd, since an initrd should be placed near end of | 434 | memory to the kernel. This affects the possible placement of |
435 | an initrd, since an initrd should be placed near end of | ||
382 | memory. Note that this is an option to *both* the kernel and | 436 | memory. Note that this is an option to *both* the kernel and |
383 | the bootloader! | 437 | the bootloader! |
384 | 438 | ||
@@ -428,7 +482,7 @@ In our example from above, we would do: | |||
428 | 482 | ||
429 | /* Set up the real-mode kernel stack */ | 483 | /* Set up the real-mode kernel stack */ |
430 | _SS = seg; | 484 | _SS = seg; |
431 | _SP = 0x9000; /* Load SP immediately after loading SS! */ | 485 | _SP = heap_end; |
432 | 486 | ||
433 | _DS = _ES = _FS = _GS = seg; | 487 | _DS = _ES = _FS = _GS = seg; |
434 | jmp_far(seg+0x20, 0); /* Run the kernel */ | 488 | jmp_far(seg+0x20, 0); /* Run the kernel */ |
@@ -460,8 +514,9 @@ IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and | |||
460 | code32_start: | 514 | code32_start: |
461 | A 32-bit flat-mode routine *jumped* to immediately after the | 515 | A 32-bit flat-mode routine *jumped* to immediately after the |
462 | transition to protected mode, but before the kernel is | 516 | transition to protected mode, but before the kernel is |
463 | uncompressed. No segments, except CS, are set up; you should | 517 | uncompressed. No segments, except CS, are guaranteed to be |
464 | set them up to KERNEL_DS (0x18) yourself. | 518 | set up (current kernels do, but older ones do not); you should |
519 | set them up to BOOT_DS (0x18) yourself. | ||
465 | 520 | ||
466 | After completing your hook, you should jump to the address | 521 | After completing your hook, you should jump to the address |
467 | that was in this field before your boot loader overwrote it. | 522 | that was in this field before your boot loader overwrote it. |