xref: /OK3568_Linux_fs/u-boot/arch/x86/cpu/start16.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/*
2*4882a593Smuzhiyun *  U-Boot - x86 Startup Code
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * (C) Copyright 2008-2011
5*4882a593Smuzhiyun * Graeme Russ, <graeme.russ@gmail.com>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * (C) Copyright 2002,2003
8*4882a593Smuzhiyun * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * SPDX-License-Identifier:	GPL-2.0+
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun#include <asm/global_data.h>
14*4882a593Smuzhiyun#include <asm/processor-flags.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun#define BOOT_SEG	0xffff0000	/* linear segment of boot code */
17*4882a593Smuzhiyun#define a32		.byte 0x67;
18*4882a593Smuzhiyun#define o32		.byte 0x66;
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun.section .start16, "ax"
21*4882a593Smuzhiyun.code16
22*4882a593Smuzhiyun.globl start16
23*4882a593Smuzhiyunstart16:
24*4882a593Smuzhiyun	/* Save BIST */
25*4882a593Smuzhiyun	movl	%eax, %ecx
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun	/* Set the Cold Boot / Hard Reset flag */
28*4882a593Smuzhiyun	movl	$GD_FLG_COLD_BOOT, %ebx
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun	xorl	%eax, %eax
31*4882a593Smuzhiyun	movl	%eax, %cr3	/* Invalidate TLB */
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun	/* Turn off cache (this might require a 486-class CPU) */
34*4882a593Smuzhiyun	movl	%cr0, %eax
35*4882a593Smuzhiyun	orl	$(X86_CR0_NW | X86_CR0_CD), %eax
36*4882a593Smuzhiyun	movl	%eax, %cr0
37*4882a593Smuzhiyun	wbinvd
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun	/* load the temporary Global Descriptor Table */
40*4882a593Smuzhiyuno32 cs	lidt	idt_ptr
41*4882a593Smuzhiyuno32 cs	lgdt	gdt_ptr
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun	/* Now, we enter protected mode */
44*4882a593Smuzhiyun	movl	%cr0, %eax
45*4882a593Smuzhiyun	orl	$X86_CR0_PE, %eax
46*4882a593Smuzhiyun	movl	%eax, %cr0
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun	/* Flush the prefetch queue */
49*4882a593Smuzhiyun	jmp	ff
50*4882a593Smuzhiyunff:
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun	/* Finally restore BIST and jump to the 32-bit initialization code */
53*4882a593Smuzhiyun	movw	$code32start, %ax
54*4882a593Smuzhiyun	movw	%ax, %bp
55*4882a593Smuzhiyun	movl	%ecx, %eax
56*4882a593Smuzhiyuno32 cs	ljmp	*(%bp)
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun	/* 48-bit far pointer */
59*4882a593Smuzhiyuncode32start:
60*4882a593Smuzhiyun	.long	_start		/* offset */
61*4882a593Smuzhiyun	.word	0x10		/* segment */
62*4882a593Smuzhiyun
63*4882a593Smuzhiyunidt_ptr:
64*4882a593Smuzhiyun	.word	0		/* limit */
65*4882a593Smuzhiyun	.long	0		/* base */
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun	/*
68*4882a593Smuzhiyun	 * The following Global Descriptor Table is just enough to get us into
69*4882a593Smuzhiyun	 * 'Flat Protected Mode' - It will be discarded as soon as the final
70*4882a593Smuzhiyun	 * GDT is setup in a safe location in RAM
71*4882a593Smuzhiyun	 */
72*4882a593Smuzhiyungdt_ptr:
73*4882a593Smuzhiyun	.word	0x1f		/* limit (31 bytes = 4 GDT entries - 1) */
74*4882a593Smuzhiyun	.long	BOOT_SEG + gdt_rom	/* base */
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun	/* Some CPUs are picky about GDT alignment... */
77*4882a593Smuzhiyun	.align	16
78*4882a593Smuzhiyun.globl gdt_rom
79*4882a593Smuzhiyungdt_rom:
80*4882a593Smuzhiyun	/*
81*4882a593Smuzhiyun	 * The GDT table ...
82*4882a593Smuzhiyun	 *
83*4882a593Smuzhiyun	 *	 Selector	Type
84*4882a593Smuzhiyun	 *	 0x00		NULL
85*4882a593Smuzhiyun	 *	 0x08		Unused
86*4882a593Smuzhiyun	 *	 0x10		32bit code
87*4882a593Smuzhiyun	 *	 0x18		32bit data/stack
88*4882a593Smuzhiyun	 */
89*4882a593Smuzhiyun	/* The NULL Desciptor - Mandatory */
90*4882a593Smuzhiyun	.word	0x0000		/* limit_low */
91*4882a593Smuzhiyun	.word	0x0000		/* base_low */
92*4882a593Smuzhiyun	.byte	0x00		/* base_middle */
93*4882a593Smuzhiyun	.byte	0x00		/* access */
94*4882a593Smuzhiyun	.byte	0x00		/* flags + limit_high */
95*4882a593Smuzhiyun	.byte	0x00		/* base_high */
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun	/* Unused Desciptor - (matches Linux) */
98*4882a593Smuzhiyun	.word	0x0000		/* limit_low */
99*4882a593Smuzhiyun	.word	0x0000		/* base_low */
100*4882a593Smuzhiyun	.byte	0x00		/* base_middle */
101*4882a593Smuzhiyun	.byte	0x00		/* access */
102*4882a593Smuzhiyun	.byte	0x00		/* flags + limit_high */
103*4882a593Smuzhiyun	.byte	0x00		/* base_high */
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun	/*
106*4882a593Smuzhiyun	 * The Code Segment Descriptor:
107*4882a593Smuzhiyun	 * - Base   = 0x00000000
108*4882a593Smuzhiyun	 * - Size   = 4GB
109*4882a593Smuzhiyun	 * - Access = Present, Ring 0, Exec (Code), Readable
110*4882a593Smuzhiyun	 * - Flags  = 4kB Granularity, 32-bit
111*4882a593Smuzhiyun	 */
112*4882a593Smuzhiyun	.word	0xffff		/* limit_low */
113*4882a593Smuzhiyun	.word	0x0000		/* base_low */
114*4882a593Smuzhiyun	.byte	0x00		/* base_middle */
115*4882a593Smuzhiyun	.byte	0x9b		/* access */
116*4882a593Smuzhiyun	.byte	0xcf		/* flags + limit_high */
117*4882a593Smuzhiyun	.byte	0x00		/* base_high */
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun	/*
120*4882a593Smuzhiyun	 * The Data Segment Descriptor:
121*4882a593Smuzhiyun	 * - Base   = 0x00000000
122*4882a593Smuzhiyun	 * - Size   = 4GB
123*4882a593Smuzhiyun	 * - Access = Present, Ring 0, Non-Exec (Data), Writable
124*4882a593Smuzhiyun	 * - Flags  = 4kB Granularity, 32-bit
125*4882a593Smuzhiyun	 */
126*4882a593Smuzhiyun	.word	0xffff		/* limit_low */
127*4882a593Smuzhiyun	.word	0x0000		/* base_low */
128*4882a593Smuzhiyun	.byte	0x00		/* base_middle */
129*4882a593Smuzhiyun	.byte	0x93		/* access */
130*4882a593Smuzhiyun	.byte	0xcf		/* flags + limit_high */
131*4882a593Smuzhiyun	.byte	0x00		/* base_high */
132