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