@@ -69,6 +69,7 @@ KBUILD_CFLAGS := $(REALMODE_CFLAGS) -D_SETUP
KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
+KBUILD_CFLAGS += $(call cc-option,-Oz)
GCOV_PROFILE := n
UBSAN_SANITIZE := n
@@ -36,6 +36,10 @@ SYSSEG = 0x1000 /* historical load address >> 4 */
#define ROOT_RDONLY 1
#endif
+ /* The setup block has a fixed size: 32 * 512 == 16k */
+ .globl setup_size
+ .set setup_size, 0x4000
+
.code16
.section ".bstext", "ax"
#ifdef CONFIG_EFI_STUB
@@ -231,7 +235,7 @@ sentinel: .byte 0xff, 0xff /* Used to detect broken loaders */
.globl hdr
hdr:
-setup_sects: .byte 0 /* Filled in by build.c */
+setup_sects: .byte (setup_size / 512) - 1
root_flags: .word ROOT_RDONLY
syssize: .long 0 /* Filled in by build.c */
ram_size: .word 0 /* Obsolete */
@@ -57,6 +57,7 @@ SECTIONS
}
ASSERT(_end <= 0x8000, "Setup too big!")
+ ASSERT(__bss_start <= setup_size, "Setup image size too big!")
ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!")
/* Necessary for the very-old-loader check to work... */
ASSERT(__end_init <= 5*512, "init sections too big!")
@@ -40,12 +40,10 @@ typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
-/* Minimal number of setup sectors */
-#define SETUP_SECT_MIN 5
-#define SETUP_SECT_MAX 64
+#define SETUP_SECT_NUM 32
/* This must be large enough to hold the entire setup */
-u8 buf[SETUP_SECT_MAX*512];
+u8 buf[(SETUP_SECT_NUM+1)*512];
#define PECOFF_RELOC_RESERVE 0x20
@@ -360,8 +358,9 @@ int main(int argc, char ** argv)
/* Pad unused space with zeros */
setup_sectors = (c + 511) / 512;
- if (setup_sectors < SETUP_SECT_MIN)
- setup_sectors = SETUP_SECT_MIN;
+ if (setup_sectors > SETUP_SECT_NUM)
+ die("setup size exceeds maximum");
+ setup_sectors = SETUP_SECT_NUM;
i = setup_sectors*512;
memset(buf+c, 0, i-c);
@@ -388,7 +387,6 @@ int main(int argc, char ** argv)
#endif
/* Patch the setup code with the appropriate size parameters */
- buf[0x1f1] = setup_sectors-1;
put_unaligned_le32(sys_size, &buf[0x1f4]);
update_pecoff_text(setup_sectors * 512, i + (sys_size * 16));
The setup block contains the real mode startup code that is used when booting from a legacy BIOS, along with the boot_params/setup_data that is used by legacy x86 bootloaders to pass the command line and initial ramdisk parameters, among other things. The setup block also contains the PE/COFF header of the entire combined image, which includes the compressed kernel image, the decompressor and the EFI stub. This PE header describes the layout of the executable image in memory, and currently, the fact that the setup block precedes it makes it rather fiddly to get the right values into the right place in the final image. One complicating factor here is the variable setup block size, and given that we will need to round up the setup block size to page size anyway in a subsequent patch (in order to be able to use different permissions for .text and .data), let's round it up to a fixed size of 16 KiB and be done with it. Note that Clang does not optimize for size as aggressively as GCC when using the -Os option, but it supports -Oz for this purpose, so pass that if the compiler supports it. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> --- arch/x86/boot/Makefile | 1 + arch/x86/boot/header.S | 6 +++++- arch/x86/boot/setup.ld | 1 + arch/x86/boot/tools/build.c | 12 +++++------- 4 files changed, 12 insertions(+), 8 deletions(-)