x86: Move GDT to a safe location in RAM
Currently, the GDT is either located in FLASH or in the non-relocated U-Boot image in RAM. Both of these locations are unsafe as those locations can be erased during a U-Boot update. Move the GDT into the highest available memory location and relocate U-Boot to just below it Signed-off-by: Graeme Russ <graeme.russ@gmail.com>
This commit is contained in:
		
							parent
							
								
									077e1958ca
								
							
						
					
					
						commit
						c14a3669b2
					
				|  | @ -100,6 +100,53 @@ mem_init_ret: | |||
| 	jmp     get_mem_size | ||||
| get_mem_size_ret: | ||||
| 
 | ||||
| 	/* | ||||
| 	 * We are now in 'Flat Protected Mode' and we know how much memory | ||||
| 	 * the board has. The (temporary) Global Descriptor Table is not | ||||
| 	 * in a 'Safe' place (it is either in Flash which can be erased or | ||||
| 	 * reprogrammed or in a fail-safe boot-strap image which could be | ||||
| 	 * over-written). | ||||
| 	 * | ||||
| 	 * Move the final gdt to a safe place (top of RAM) and load it. | ||||
| 	 * This is not a trivial excercise - the lgdt instruction does not | ||||
| 	 * have a register operand (memory only) and we may well be | ||||
| 	 * running from Flash, so self modifying code will not work here. | ||||
| 	 * To overcome this, we copy a stub into upper memory along with | ||||
| 	 * the GDT. | ||||
| 	 */ | ||||
| 
 | ||||
| 	/* Reduce upper memory limit by (Stub + GDT Pointer + GDT) */ | ||||
| 	subl	$(end_gdt_setup - start_gdt_setup), %eax | ||||
| 
 | ||||
| 	/* Copy the GDT and Stub */ | ||||
| 	movl	$start_gdt_setup, %esi | ||||
| 	movl	%eax, %edi | ||||
| 	movl	$(end_gdt_setup - start_gdt_setup), %ecx | ||||
| 	shrl	$2, %ecx | ||||
| 	cld | ||||
| 	rep	movsl | ||||
| 
 | ||||
| 	/* write the lgdt 'parameter' */ | ||||
| 	subl	$(jmp_instr - start_gdt_setup - 4), %ebp | ||||
| 	addl	%eax, %ebp | ||||
| 	movl	$(gdt_ptr - start_gdt_setup), %ebx | ||||
| 	addl	%eax, %ebx | ||||
| 	movl	%ebx, (%ebp) | ||||
| 
 | ||||
| 	/* write the gdt address into the pointer */ | ||||
| 	movl	$(gdt_addr - start_gdt_setup), %ebp | ||||
| 	addl	%eax, %ebp | ||||
| 	movl	$(gdt - start_gdt_setup), %ebx | ||||
| 	addl	%eax, %ebx | ||||
| 	movl	%ebx, (%ebp) | ||||
| 
 | ||||
| 	/* Save the return address */ | ||||
| 	movl	$load_gdt_ret, %ebp | ||||
| 
 | ||||
| 	/* Load the new (safe) Global Descriptor Table */ | ||||
| 	jmp	*%eax | ||||
| 
 | ||||
| load_gdt_ret: | ||||
| 	/* Check we have enough memory for stack */ | ||||
| 	movl	$CONFIG_SYS_STACK_SIZE, %ecx | ||||
| 	cmpl	%ecx, %eax | ||||
|  | @ -174,3 +221,52 @@ die:	hlt | |||
| blank_idt_ptr: | ||||
| 	.word	0		/* limit */ | ||||
| 	.long	0		/* base */ | ||||
| 
 | ||||
| .align 4
 | ||||
| start_gdt_setup: | ||||
| 	lgdt	gdt_ptr | ||||
| jmp_instr: | ||||
| 	jmp	*%ebp | ||||
| 
 | ||||
| .align 4
 | ||||
| gdt_ptr: | ||||
| 	.word	0x30		/* limit (48 bytes = 6 GDT entries) */ | ||||
| gdt_addr: | ||||
| 	.long	gdt		/* base */ | ||||
| 
 | ||||
| 	/* The GDT table ... | ||||
| 	 * | ||||
| 	 *	 Selector	Type | ||||
| 	 *	 0x00		NULL | ||||
| 	 *	 0x08		Unused | ||||
| 	 *	 0x10		32bit code | ||||
| 	 *	 0x18		32bit data/stack | ||||
| 	 *	 0x20		16bit code | ||||
| 	 *	 0x28		16bit data/stack | ||||
| 	 */ | ||||
| 
 | ||||
| .align 4
 | ||||
| gdt: | ||||
| 	.word	0, 0, 0, 0	/* NULL  */ | ||||
| 	.word	0, 0, 0, 0	/* unused */ | ||||
| 
 | ||||
| 	.word	0xFFFF		/* 4Gb - (0x100000*0x1000 = 4Gb) */ | ||||
| 	.word	0		/* base address = 0 */ | ||||
| 	.word	0x9B00		/* code read/exec */ | ||||
| 	.word	0x00CF		/* granularity = 4096, 386 (+5th nibble of limit) */ | ||||
| 
 | ||||
| 	.word	0xFFFF		/* 4Gb - (0x100000*0x1000 = 4Gb) */ | ||||
| 	.word	0x0		/* base address = 0 */ | ||||
| 	.word	0x9300		/* data read/write */ | ||||
| 	.word	0x00CF		/* granularity = 4096, 386 (+5th nibble of limit) */ | ||||
| 
 | ||||
| 	.word	0xFFFF		/* 64kb */ | ||||
| 	.word	0		/* base address = 0 */ | ||||
| 	.word	0x9b00		/* data read/write */ | ||||
| 	.word	0x0010		/* granularity = 1  (+5th nibble of limit) */ | ||||
| 
 | ||||
| 	.word	0xFFFF		/* 64kb */ | ||||
| 	.word	0		/* base address = 0 */ | ||||
| 	.word	0x9300		/* data read/write */ | ||||
| 	.word	0x0010		/* granularity = 1 (+5th nibble of limit) */ | ||||
| end_gdt_setup: | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ board_init16_ret: | |||
| 	movl	%eax, %cr0 | ||||
| 	wbinvd | ||||
| 
 | ||||
| 	/* load the descriptor tables */ | ||||
| 	/* load the temporary Global Descriptor Table */ | ||||
| o32 cs	lgdt	gdt_ptr | ||||
| 
 | ||||
| 	/* Now, we enter protected mode */ | ||||
|  | @ -68,8 +68,13 @@ code32start: | |||
| 	.long	_start		/* offset */ | ||||
| 	.word	0x10		/* segment */ | ||||
| 
 | ||||
| /* | ||||
|  * The following Global Descriptor Table is just enough to get us into | ||||
|  * 'Flat Protected Mode' - It will be discarded as soon as the final | ||||
|  * GDT is setup in a safe location in RAM | ||||
|  */ | ||||
| gdt_ptr: | ||||
| 	.word	0x30		/* limit (48 bytes = 6 GDT entries) */ | ||||
| 	.word	0x20		/* limit (32 bytes = 4 GDT entries) */ | ||||
| 	.long	BOOT_SEG + gdt	/* base */ | ||||
| 
 | ||||
| 	/* The GDT table ... | ||||
|  | @ -79,8 +84,6 @@ gdt_ptr: | |||
| 	 *	 0x08		Unused | ||||
| 	 *	 0x10		32bit code | ||||
| 	 *	 0x18		32bit data/stack | ||||
| 	 *	 0x20		16bit code | ||||
| 	 *	 0x28		16bit data/stack | ||||
| 	 */ | ||||
| 
 | ||||
| gdt: | ||||
|  | @ -96,13 +99,3 @@ gdt: | |||
| 	.word	0x0		/* base address = 0 */ | ||||
| 	.word	0x9300		/* data read/write */ | ||||
| 	.word	0x00CF		/* granularity = 4096, 386 (+5th nibble of limit) */ | ||||
| 
 | ||||
| 	.word	0xFFFF		/* 64kb */ | ||||
| 	.word	0		/* base address = 0 */ | ||||
| 	.word	0x9b00		/* data read/write */ | ||||
| 	.word	0x0010		/* granularity = 1  (+5th nibble of limit) */ | ||||
| 
 | ||||
| 	.word	0xFFFF		/* 64kb */ | ||||
| 	.word	0		/* base address = 0 */ | ||||
| 	.word	0x9300		/* data read/write */ | ||||
| 	.word	0x0010		/* granularity = 1 (+5th nibble of limit) */ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue