diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-05-07 19:54:11 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-05-11 20:45:06 -0400 |
commit | 5031296c57024a78ddad4edfc993367dbf4abb98 (patch) | |
tree | 7506daf7aabf25a5ec567fcd2e644fe22cd91eca | |
parent | fe83fcc0a14dcf71996de5eb84771b2369ba7abc (diff) |
x86: add extension fields for bootloader type and version
A long ago, in days of yore, it all began with a god named Thor.
There were vikings and boats and some plans for a Linux kernel
header. Unfortunately, a single 8-bit field was used for bootloader
type and version. This has generally worked without *too* much pain,
but we're getting close to flat running out of ID fields.
Add extension fields for both type and version. The type will be
extended if it the old field is 0xE; the version is a simple MSB
extension.
Keep /proc/sys/kernel/bootloader_type containing
(type << 4) + (ver & 0xf) for backwards compatiblity, but also add
/proc/sys/kernel/bootloader_version which contains the full version
number.
[ Impact: new feature to support more bootloaders ]
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | Documentation/x86/boot.txt | 59 | ||||
-rw-r--r-- | arch/x86/boot/header.S | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/bootparam.h | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/processor.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 10 | ||||
-rw-r--r-- | kernel/sysctl.c | 8 |
6 files changed, 76 insertions, 11 deletions
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index cf8dfc70a118..8da3a795083f 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt | |||
@@ -50,10 +50,9 @@ Protocol 2.08: (Kernel 2.6.26) Added crc32 checksum and ELF format | |||
50 | Protocol 2.09: (Kernel 2.6.26) Added a field of 64-bit physical | 50 | Protocol 2.09: (Kernel 2.6.26) Added a field of 64-bit physical |
51 | pointer to single linked list of struct setup_data. | 51 | pointer to single linked list of struct setup_data. |
52 | 52 | ||
53 | Protocol 2.10: (Kernel 2.6.31) A protocol for relaxed alignment | 53 | Protocol 2.10: (Kernel 2.6.31) Added a protocol for relaxed alignment |
54 | beyond the kernel_alignment added, new init_size and | 54 | beyond the kernel_alignment added, new init_size and |
55 | pref_address fields. | 55 | pref_address fields. Added extended boot loader IDs. |
56 | |||
57 | 56 | ||
58 | **** MEMORY LAYOUT | 57 | **** MEMORY LAYOUT |
59 | 58 | ||
@@ -173,7 +172,8 @@ Offset Proto Name Meaning | |||
173 | 021C/4 2.00+ ramdisk_size initrd size (set by boot loader) | 172 | 021C/4 2.00+ ramdisk_size initrd size (set by boot loader) |
174 | 0220/4 2.00+ bootsect_kludge DO NOT USE - for bootsect.S use only | 173 | 0220/4 2.00+ bootsect_kludge DO NOT USE - for bootsect.S use only |
175 | 0224/2 2.01+ heap_end_ptr Free memory after setup end | 174 | 0224/2 2.01+ heap_end_ptr Free memory after setup end |
176 | 0226/2 N/A pad1 Unused | 175 | 0226/1 2.02+(3 ext_loader_ver Extended boot loader version |
176 | 0227/1 2.02+(3 ext_loader_type Extended boot loader ID | ||
177 | 0228/4 2.02+ cmd_line_ptr 32-bit pointer to the kernel command line | 177 | 0228/4 2.02+ cmd_line_ptr 32-bit pointer to the kernel command line |
178 | 022C/4 2.03+ ramdisk_max Highest legal initrd address | 178 | 022C/4 2.03+ ramdisk_max Highest legal initrd address |
179 | 0230/4 2.05+ kernel_alignment Physical addr alignment required for kernel | 179 | 0230/4 2.05+ kernel_alignment Physical addr alignment required for kernel |
@@ -197,6 +197,8 @@ Offset Proto Name Meaning | |||
197 | field are unusable, which means the size of a bzImage kernel | 197 | field are unusable, which means the size of a bzImage kernel |
198 | cannot be determined. | 198 | cannot be determined. |
199 | 199 | ||
200 | (3) Ignored, but safe to set, for boot protocols 2.02-2.09. | ||
201 | |||
200 | If the "HdrS" (0x53726448) magic number is not found at offset 0x202, | 202 | If the "HdrS" (0x53726448) magic number is not found at offset 0x202, |
201 | the boot protocol version is "old". Loading an old kernel, the | 203 | the boot protocol version is "old". Loading an old kernel, the |
202 | following parameters should be assumed: | 204 | following parameters should be assumed: |
@@ -350,18 +352,32 @@ Protocol: 2.00+ | |||
350 | 0xTV here, where T is an identifier for the boot loader and V is | 352 | 0xTV here, where T is an identifier for the boot loader and V is |
351 | a version number. Otherwise, enter 0xFF here. | 353 | a version number. Otherwise, enter 0xFF here. |
352 | 354 | ||
355 | For boot loader IDs above T = 0xD, write T = 0xE to this field and | ||
356 | write the extended ID minus 0x10 to the ext_loader_type field. | ||
357 | Similarly, the ext_loader_ver field can be used to provide more than | ||
358 | four bits for the bootloader version. | ||
359 | |||
360 | For example, for T = 0x15, V = 0x234, write: | ||
361 | |||
362 | type_of_loader <- 0xE4 | ||
363 | ext_loader_type <- 0x05 | ||
364 | ext_loader_ver <- 0x23 | ||
365 | |||
353 | Assigned boot loader ids: | 366 | Assigned boot loader ids: |
354 | 0 LILO (0x00 reserved for pre-2.00 bootloader) | 367 | 0 LILO (0x00 reserved for pre-2.00 bootloader) |
355 | 1 Loadlin | 368 | 1 Loadlin |
356 | 2 bootsect-loader (0x20, all other values reserved) | 369 | 2 bootsect-loader (0x20, all other values reserved) |
357 | 3 SYSLINUX | 370 | 3 Syslinux |
358 | 4 EtherBoot | 371 | 4 Etherboot/gPXE |
359 | 5 ELILO | 372 | 5 ELILO |
360 | 7 GRUB | 373 | 7 GRUB |
361 | 8 U-BOOT | 374 | 8 U-Boot |
362 | 9 Xen | 375 | 9 Xen |
363 | A Gujin | 376 | A Gujin |
364 | B Qemu | 377 | B Qemu |
378 | C Arcturus Networks uCbootloader | ||
379 | E Extended (see ext_loader_type) | ||
380 | F Special (0xFF = undefined) | ||
365 | 381 | ||
366 | Please contact <hpa@zytor.com> if you need a bootloader ID | 382 | Please contact <hpa@zytor.com> if you need a bootloader ID |
367 | value assigned. | 383 | value assigned. |
@@ -460,6 +476,35 @@ Protocol: 2.01+ | |||
460 | Set this field to the offset (from the beginning of the real-mode | 476 | Set this field to the offset (from the beginning of the real-mode |
461 | code) of the end of the setup stack/heap, minus 0x0200. | 477 | code) of the end of the setup stack/heap, minus 0x0200. |
462 | 478 | ||
479 | Field name: ext_loader_ver | ||
480 | Type: write (optional) | ||
481 | Offset/size: 0x226/1 | ||
482 | Protocol: 2.02+ | ||
483 | |||
484 | This field is used as an extension of the version number in the | ||
485 | type_of_loader field. The total version number is considered to be | ||
486 | (type_of_loader & 0x0f) + (ext_loader_ver << 4). | ||
487 | |||
488 | The use of this field is boot loader specific. If not written, it | ||
489 | is zero. | ||
490 | |||
491 | Kernels prior to 2.6.31 did not recognize this field, but it is safe | ||
492 | to write for protocol version 2.02 or higher. | ||
493 | |||
494 | Field name: ext_loader_type | ||
495 | Type: write (obligatory if (type_of_loader & 0xf0) == 0xe0) | ||
496 | Offset/size: 0x227/1 | ||
497 | Protocol: 2.02+ | ||
498 | |||
499 | This field is used as an extension of the type number in | ||
500 | type_of_loader field. If the type in type_of_loader is 0xE, then | ||
501 | the actual type is (ext_loader_type + 0x10). | ||
502 | |||
503 | This field is ignored if the type in type_of_loader is not 0xE. | ||
504 | |||
505 | Kernels prior to 2.6.31 did not recognize this field, but it is safe | ||
506 | to write for protocol version 2.02 or higher. | ||
507 | |||
463 | Field name: cmd_line_ptr | 508 | Field name: cmd_line_ptr |
464 | Type: write (obligatory) | 509 | Type: write (obligatory) |
465 | Offset/size: 0x228/4 | 510 | Offset/size: 0x228/4 |
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index a0b426978d55..68c3bfbaff24 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S | |||
@@ -169,7 +169,11 @@ heap_end_ptr: .word _end+STACK_SIZE-512 | |||
169 | # end of setup code can be used by setup | 169 | # end of setup code can be used by setup |
170 | # for local heap purposes. | 170 | # for local heap purposes. |
171 | 171 | ||
172 | pad1: .word 0 | 172 | ext_loader_ver: |
173 | .byte 0 # Extended boot loader version | ||
174 | ext_loader_type: | ||
175 | .byte 0 # Extended boot loader type | ||
176 | |||
173 | cmd_line_ptr: .long 0 # (Header version 0x0202 or later) | 177 | cmd_line_ptr: .long 0 # (Header version 0x0202 or later) |
174 | # If nonzero, a 32-bit pointer | 178 | # If nonzero, a 32-bit pointer |
175 | # to the kernel command line. | 179 | # to the kernel command line. |
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h index 433adaebf9b6..1724e8de317c 100644 --- a/arch/x86/include/asm/bootparam.h +++ b/arch/x86/include/asm/bootparam.h | |||
@@ -50,7 +50,8 @@ struct setup_header { | |||
50 | __u32 ramdisk_size; | 50 | __u32 ramdisk_size; |
51 | __u32 bootsect_kludge; | 51 | __u32 bootsect_kludge; |
52 | __u16 heap_end_ptr; | 52 | __u16 heap_end_ptr; |
53 | __u16 _pad1; | 53 | __u8 ext_loader_ver; |
54 | __u8 ext_loader_type; | ||
54 | __u32 cmd_line_ptr; | 55 | __u32 cmd_line_ptr; |
55 | __u32 initrd_addr_max; | 56 | __u32 initrd_addr_max; |
56 | __u32 kernel_alignment; | 57 | __u32 kernel_alignment; |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index fcf4d92e7e04..6384d25121ca 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -814,6 +814,7 @@ extern unsigned int BIOS_revision; | |||
814 | 814 | ||
815 | /* Boot loader type from the setup header: */ | 815 | /* Boot loader type from the setup header: */ |
816 | extern int bootloader_type; | 816 | extern int bootloader_type; |
817 | extern int bootloader_version; | ||
817 | 818 | ||
818 | extern char ignore_fpu_irq; | 819 | extern char ignore_fpu_irq; |
819 | 820 | ||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index b4158439bf63..2b093451aec9 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -214,8 +214,8 @@ unsigned long mmu_cr4_features; | |||
214 | unsigned long mmu_cr4_features = X86_CR4_PAE; | 214 | unsigned long mmu_cr4_features = X86_CR4_PAE; |
215 | #endif | 215 | #endif |
216 | 216 | ||
217 | /* Boot loader ID as an integer, for the benefit of proc_dointvec */ | 217 | /* Boot loader ID and version as integers, for the benefit of proc_dointvec */ |
218 | int bootloader_type; | 218 | int bootloader_type, bootloader_version; |
219 | 219 | ||
220 | /* | 220 | /* |
221 | * Setup options | 221 | * Setup options |
@@ -706,6 +706,12 @@ void __init setup_arch(char **cmdline_p) | |||
706 | #endif | 706 | #endif |
707 | saved_video_mode = boot_params.hdr.vid_mode; | 707 | saved_video_mode = boot_params.hdr.vid_mode; |
708 | bootloader_type = boot_params.hdr.type_of_loader; | 708 | bootloader_type = boot_params.hdr.type_of_loader; |
709 | if ((bootloader_type >> 4) == 0xe) { | ||
710 | bootloader_type &= 0xf; | ||
711 | bootloader_type |= (boot_params.hdr.ext_loader_type+0x10) << 4; | ||
712 | } | ||
713 | bootloader_version = bootloader_type & 0xf; | ||
714 | bootloader_version |= boot_params.hdr.ext_loader_ver << 4; | ||
709 | 715 | ||
710 | #ifdef CONFIG_BLK_DEV_RAM | 716 | #ifdef CONFIG_BLK_DEV_RAM |
711 | rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK; | 717 | rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK; |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index e3d2c7dd59b9..cf91c9317b26 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -729,6 +729,14 @@ static struct ctl_table kern_table[] = { | |||
729 | }, | 729 | }, |
730 | { | 730 | { |
731 | .ctl_name = CTL_UNNUMBERED, | 731 | .ctl_name = CTL_UNNUMBERED, |
732 | .procname = "bootloader_version", | ||
733 | .data = &bootloader_version, | ||
734 | .maxlen = sizeof (int), | ||
735 | .mode = 0444, | ||
736 | .proc_handler = &proc_dointvec, | ||
737 | }, | ||
738 | { | ||
739 | .ctl_name = CTL_UNNUMBERED, | ||
732 | .procname = "kstack_depth_to_print", | 740 | .procname = "kstack_depth_to_print", |
733 | .data = &kstack_depth_to_print, | 741 | .data = &kstack_depth_to_print, |
734 | .maxlen = sizeof(int), | 742 | .maxlen = sizeof(int), |