blob: 865a49731e57cc89df217f2a690bc3f989353062 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0+ */
wdenk591dda52002-11-18 00:14:45 +00002/*
Bin Meng65db0c92015-01-20 11:25:44 +08003 * U-Boot - x86 Startup Code
wdenk591dda52002-11-18 00:14:45 +00004 *
Graeme Russ45fc1d82011-04-13 19:43:26 +10005 * (C) Copyright 2008-2011
6 * Graeme Russ, <graeme.russ@gmail.com>
7 *
8 * (C) Copyright 2002,2003
Albert ARIBAUD60fbc8d2011-08-04 18:45:45 +02009 * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
wdenk591dda52002-11-18 00:14:45 +000010 */
11
Graeme Russ93efcb22011-02-12 15:11:32 +110012#include <asm/processor-flags.h>
wdenk591dda52002-11-18 00:14:45 +000013
14#define BOOT_SEG 0xffff0000 /* linear segment of boot code */
wdenk591dda52002-11-18 00:14:45 +000015
16.section .start16, "ax"
17.code16
18.globl start16
wdenk57b2d802003-06-27 21:31:46 +000019start16:
Simon Glass1f4476c2014-11-06 13:20:10 -070020 /* Save BIST */
21 movl %eax, %ecx
22
Simon Glass727c4142014-11-06 13:20:03 -070023 xorl %eax, %eax
Bin Meng65db0c92015-01-20 11:25:44 +080024 movl %eax, %cr3 /* Invalidate TLB */
Simon Glass727c4142014-11-06 13:20:03 -070025
Simon Glasscbfd7ff2014-11-06 13:20:01 -070026 /* Turn off cache (this might require a 486-class CPU) */
Wolfgang Denka1be4762008-05-20 16:00:29 +020027 movl %cr0, %eax
Ondrej Kupka19c114a2011-09-30 21:05:11 +110028 orl $(X86_CR0_NW | X86_CR0_CD), %eax
Wolfgang Denka1be4762008-05-20 16:00:29 +020029 movl %eax, %cr0
Andy Shevchenkof3514a62020-02-17 17:30:12 +020030 wbinvd
wdenk57b2d802003-06-27 21:31:46 +000031
Graeme Russ59da5a52010-04-24 00:05:43 +100032 /* load the temporary Global Descriptor Table */
Masahiro Yamada19f2a6d2019-12-03 14:20:49 +090033data32 cs lidt idt_ptr
34data32 cs lgdt gdt_ptr
wdenk591dda52002-11-18 00:14:45 +000035
wdenk591dda52002-11-18 00:14:45 +000036 /* Now, we enter protected mode */
Wolfgang Denka1be4762008-05-20 16:00:29 +020037 movl %cr0, %eax
Graeme Russ93efcb22011-02-12 15:11:32 +110038 orl $X86_CR0_PE, %eax
Wolfgang Denka1be4762008-05-20 16:00:29 +020039 movl %eax, %cr0
wdenk57b2d802003-06-27 21:31:46 +000040
wdenk591dda52002-11-18 00:14:45 +000041 /* Flush the prefetch queue */
Wolfgang Denka1be4762008-05-20 16:00:29 +020042 jmp ff
wdenk591dda52002-11-18 00:14:45 +000043ff:
Simon Glass1f4476c2014-11-06 13:20:10 -070044
Bin Meng65db0c92015-01-20 11:25:44 +080045 /* Finally restore BIST and jump to the 32-bit initialization code */
Simon Glass1f4476c2014-11-06 13:20:10 -070046 movl %ecx, %eax
Masahiro Yamada80f283b2019-12-03 14:28:58 +090047data32 cs ljmp *code32start
wdenk591dda52002-11-18 00:14:45 +000048
49 /* 48-bit far pointer */
50code32start:
Wolfgang Denka1be4762008-05-20 16:00:29 +020051 .long _start /* offset */
52 .word 0x10 /* segment */
wdenk591dda52002-11-18 00:14:45 +000053
Graeme Russ4fdcc422010-08-22 16:25:59 +100054idt_ptr:
55 .word 0 /* limit */
56 .long 0 /* base */
57
Bin Meng65db0c92015-01-20 11:25:44 +080058 /*
59 * The following Global Descriptor Table is just enough to get us into
60 * 'Flat Protected Mode' - It will be discarded as soon as the final
61 * GDT is setup in a safe location in RAM
62 */
wdenk591dda52002-11-18 00:14:45 +000063gdt_ptr:
Bin Meng0f39bc02014-10-16 22:58:35 +080064 .word 0x1f /* limit (31 bytes = 4 GDT entries - 1) */
Bin Menga3c9fb02015-06-07 11:33:13 +080065 .long BOOT_SEG + gdt_rom /* base */
wdenk591dda52002-11-18 00:14:45 +000066
Bin Meng65db0c92015-01-20 11:25:44 +080067 /* Some CPUs are picky about GDT alignment... */
68 .align 16
Bin Menga3c9fb02015-06-07 11:33:13 +080069.globl gdt_rom
70gdt_rom:
Graeme Russaf3f2c82011-12-19 14:26:18 +110071 /*
72 * The GDT table ...
wdenk591dda52002-11-18 00:14:45 +000073 *
Wolfgang Denka1be4762008-05-20 16:00:29 +020074 * Selector Type
75 * 0x00 NULL
76 * 0x08 Unused
wdenk57b2d802003-06-27 21:31:46 +000077 * 0x10 32bit code
wdenk591dda52002-11-18 00:14:45 +000078 * 0x18 32bit data/stack
wdenk591dda52002-11-18 00:14:45 +000079 */
Graeme Russaf3f2c82011-12-19 14:26:18 +110080 /* The NULL Desciptor - Mandatory */
81 .word 0x0000 /* limit_low */
82 .word 0x0000 /* base_low */
83 .byte 0x00 /* base_middle */
84 .byte 0x00 /* access */
85 .byte 0x00 /* flags + limit_high */
86 .byte 0x00 /* base_high */
wdenk591dda52002-11-18 00:14:45 +000087
Graeme Russaf3f2c82011-12-19 14:26:18 +110088 /* Unused Desciptor - (matches Linux) */
89 .word 0x0000 /* limit_low */
90 .word 0x0000 /* base_low */
91 .byte 0x00 /* base_middle */
92 .byte 0x00 /* access */
93 .byte 0x00 /* flags + limit_high */
94 .byte 0x00 /* base_high */
wdenk591dda52002-11-18 00:14:45 +000095
Graeme Russaf3f2c82011-12-19 14:26:18 +110096 /*
97 * The Code Segment Descriptor:
98 * - Base = 0x00000000
99 * - Size = 4GB
100 * - Access = Present, Ring 0, Exec (Code), Readable
101 * - Flags = 4kB Granularity, 32-bit
102 */
103 .word 0xffff /* limit_low */
104 .word 0x0000 /* base_low */
105 .byte 0x00 /* base_middle */
106 .byte 0x9b /* access */
107 .byte 0xcf /* flags + limit_high */
108 .byte 0x00 /* base_high */
wdenk591dda52002-11-18 00:14:45 +0000109
Graeme Russaf3f2c82011-12-19 14:26:18 +1100110 /*
111 * The Data Segment Descriptor:
112 * - Base = 0x00000000
113 * - Size = 4GB
114 * - Access = Present, Ring 0, Non-Exec (Data), Writable
115 * - Flags = 4kB Granularity, 32-bit
116 */
117 .word 0xffff /* limit_low */
118 .word 0x0000 /* base_low */
119 .byte 0x00 /* base_middle */
120 .byte 0x93 /* access */
121 .byte 0xcf /* flags + limit_high */
122 .byte 0x00 /* base_high */