Skip to contentSkip to conversation

x86 boot enhancements, footprint rediction 7/11

PATCH New Eric W. Biederman 1 participant 1 message Apr 17, 2002

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 x86 boot enhancements, footprint rediction 7/11

Linus please apply,

Solve the space/reliability tradeoff misc.c asks bootloaders to make, with belt and suspenders.

- modify misc.c to relocate the real mode code to maximize low memory usage.
- modify misc.c to do inplace decompression
- modify setup.S to query int12 to get the low memory size
- Introduce STAY_PUT flag for bootloaders that don't pass a command_line but still don't need the bootsector to relocate itself.

The kernel now uses approximately 78KB of memory below 1MB and 8 bytes more than the decompressesed kernel above 1MB. And if required everything except the 5KB of real mode code can go above 1MB.

The 78KB below 1MB is 5KB real mode code 10KB decompressor code 61KB bss.

The change is especially nice because now in my worst case of only using 5KB real mode data, I do better than the best case with previous kernels (assuming it isn't a zImage). And if I ever get the bootmem bootmap fixed I can put initrds down at 2.6MB and not have to worry about them getting stomped :)

Eric

arch/i386/boot/compressed/Makefile +3 -5
diff -uNr linux-2.5.8.boot.clean_32bit_entries/arch/i386/boot/compressed/Makefile linux-2.5.8.boot.footprint/arch/i386/boot/compressed/Makefile
@@ -9,8 +9,6 @@
 
 OBJECTS = $(HEAD) misc.o
 
-ZLDFLAGS = -e startup_32
-
 #
 # ZIMAGE_OFFSET is the load offset of the compression loader
 # BZIMAGE_OFFSET is the load offset of the high loaded compression loader
@@ -18,8 +16,8 @@
 ZIMAGE_OFFSET = 0x1000
 BZIMAGE_OFFSET = 0x100000
 
-ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS)
-BZLINKFLAGS = -Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS)
+ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) -T vmlinuz.lds
+BZLINKFLAGS = -Ttext $(BZIMAGE_OFFSET) -T vmlinuz.lds 
 
 all: vmlinux
 
@@ -42,7 +40,7 @@
 	rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \
 	$(OBJCOPY) $(SYSTEM) $$tmppiggy; \
 	gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \
-	echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \
+	echo "SECTIONS { .input : { *(.data) }}" > $$tmppiggy.lnk; \
 	$(LD) -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-i386 -T $$tmppiggy.lnk; \
 	rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk
 
arch/i386/boot/compressed/head.S +26 -0
diff -uNr linux-2.5.8.boot.clean_32bit_entries/arch/i386/boot/compressed/head.S linux-2.5.8.boot.footprint/arch/i386/boot/compressed/head.S
@@ -30,6 +30,20 @@
 	.globl startup_32
 	
 startup_32:
+	jmp 1f
+	.balign		4
+	.globl input_addr, input_len, output_overhang
+	.globl kernel_base, kernel_memsz, kernel_filesz
+	.globl unzip_memsz, unzip_filesz
+input_addr:		.long input_data
+input_len:		.long input_data_len
+output_overhang:	.long input_data_len # Will be set to 8 later...
+kernel_base:		.long HIGH_BASE
+kernel_memsz:		.long 0
+kernel_filesz:		.long 0
+unzip_memsz:		.long _end
+unzip_filesz:		.long _edata
+1:	
 	cld
 	cli
 
@@ -44,6 +58,18 @@
 	movl %edi, edi
 	movl %esp, esp
 	movl %ebp, ebp
+
+	/* 
+	 * Move the input data off the bss segment
+	 */
+	std
+	movl $input_data_end -1, %esi
+	movl %esi, %edi
+	addl $input_data_shift, %edi
+	movl $input_data_len, %ecx
+	rep movsb
+	cld
+	addl $input_data_shift, input_addr
 
 	/*
 	 * Setup the stack
arch/i386/boot/compressed/misc.c +123 -65

288 lines not on this page · raw message

arch/i386/boot/compressed/vmlinuz.lds +29 -0
diff -uNr linux-2.5.8.boot.clean_32bit_entries/arch/i386/boot/compressed/vmlinuz.lds linux-2.5.8.boot.footprint/arch/i386/boot/compressed/vmlinuz.lds
@@ -0,0 +1,29 @@
+/* ld script to make compressed i386 Linux kernel
+ */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(startup_32)
+SECTIONS
+{
+	. = 0x1000;
+	_text = .;			/* Text and read-only data */
+	.text : { *(.text) } = 0x9090
+	_etext = .;			/* End of text section */
+	.rodata : { *(.rodata) *(.rodata.*) }
+	.data : { 
+		*(.data) 
+		
+	}
+	_edata = .;			/* End of data section */
+	.bss _edata : { *(.bss) }
+	_end = .;
+	.input _edata : { 
+		input_data = . ;
+		*(.input)
+		input_data_end = . ;
+	}
+	input_data_len = input_data_end - input_data;
+	input_data_shift = _end - _edata;
+
+	/DISCARD/ : { *(*) }
+}		
arch/i386/boot/setup.S +21 -4
diff -uNr linux-2.5.8.boot.clean_32bit_entries/arch/i386/boot/setup.S linux-2.5.8.boot.footprint/arch/i386/boot/setup.S
@@ -106,6 +106,8 @@
 # flags, unused bits must be zero (RFU) bit within loadflags
 loadflags:
 LOADED_HIGH	= 1			# If set, the kernel is loaded high
+STAY_PUT        = 0x40                  # If set, the loader doesn't expect
+                                        # us to relocate anything
 CAN_USE_HEAP	= 0x80			# If set, the loader also has set
 					# heap_end_ptr to tell how much
 					# space behind setup.S can be used for
@@ -162,7 +164,11 @@
 					# The highest safe address for
 					# the contents of an initrd
 
-# variables private to setup.S (not for bootloaders)
+# variables private to the kernel (not for bootloaders)
+pad2:		.long	0
+real_base:	.long	REAL_BASE	# Location of real mode kernel
+real_memsz:				# Memory usage of real mode kernel
+		.long	(_esetup_heap - _setup) + DELTA_BOOTSECT
 real_filesz:				# Datasize of the real mode kernel
 		.long (_esetup - _setup) + DELTA_BOOTSECT
 trampoline:	call	start_of_setup
@@ -297,6 +303,15 @@
 #endif /* __BIG_KERNEL__ */
 
 loader_ok:
+# Get base memory size
+# The size in kilobytes is returned in %ax
+# There shouldn't be any subfunctions but just
+# in case we clear eax and ecx
+	xorl	%eax, %eax
+	xorl	%ecx, %ecx
+	int	$0x12
+	movw	%ax, (0x1e4)
+	
 # Get memory size (extended mem, kB)
 
 	xorl	%eax, %eax
@@ -604,12 +619,13 @@
 # then we load the segment descriptors
 	movw	%cs, %ax			# aka SETUPSEG
 	movw	%ax, %ds
-		
+
 # Check whether we need to be downward compatible with version <=201
+# We don't relocate if STAY_PUT is specified or we have a 202 cmd_line
+	testb  	$STAY_PUT, loadflags
+	jnz	end_move_self
 	cmpl	$0, cmd_line_ptr
 	jne	end_move_self		# loader uses version >=202 features
-	cmpb	$0x20, type_of_loader
-	je	end_move_self		# bootsect loader, we know of it
 
 # Boot loader doesnt support boot protocol version 2.02.
 # If we have our code not at 0x90000, we need to move it there now.
@@ -846,6 +862,7 @@
 	jnz	bootsect_second
 
 	movb	$0x20, %cs:type_of_loader
+	orb	$STAY_PUT, %cs:loadflags
 	movw	%es, %ax
 	shrw	$4, %ax
 	movb	%ah, %cs:bootsect_src_base+2
arch/i386/boot/tools/build.c +157 -6

191 lines not on this page · raw message

include/asm-i386/boot_param.h +7 -3
diff -uNr linux-2.5.8.boot.clean_32bit_entries/include/asm-i386/boot_param.h linux-2.5.8.boot.footprint/include/asm-i386/boot_param.h
@@ -37,7 +37,8 @@
 	struct drive_info_struct drive_info;	/* 0x80 */
 	struct sys_desc_table sys_desc_table;	/* 0xa0 */
 	__u32 alt_mem_k;			/* 0x1e0 */
-	__u8  reserved5[4];			/* 0x1e4 */
+	__u16 base_mem_k;			/* 0x1e4 */
+	__u8  reserved5[2];			/* 0x1e6 */
 	__u8  e820_map_nr;			/* 0x1e8 */
 	__u8  reserved6[8];			/* 0x1e9 */
 	__u8  setup_sects;			/* 0x1f1 */
@@ -83,8 +84,11 @@
 	/* 2.03+ */
 	__u32 ramdisk_max;			/* 0x22c */
 	/* Below this point for internal kernel use only */
-	__u32 real_filesz;			/* 0x230 */
-	__u8  reserved15[0x2d0 - 0x234];	/* 0x234 */
+	__u32 pad2;				/* 0x230 */
+	__u32 real_base;			/* 0x234 */
+	__u32 real_memsz;			/* 0x238 */
+	__u32 real_filesz;			/* 0x23c */
+	__u8  reserved15[0x2d0 - 0x240];	/* 0x240 */
 	struct e820entry e820_map[E820MAX];	/* 0x2d0 */
 						/* 0x550 */
 } __attribute__((packed));