Merge tag 'pull-sp-20240412' of https://gitlab.com/rth7680/qemu into staging
[qemu/armbru.git] / pc-bios / optionrom / pvh.S
blobe1d7f4a7a7841a4ea6b4517e29f034852a8dccfc
1 /*
2  * PVH Option ROM
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
16  *
17  * Copyright Novell Inc, 2009
18  *   Authors: Alexander Graf <agraf@suse.de>
19  *
20  * Copyright (c) 2019 Red Hat Inc.
21  *   Authors: Stefano Garzarella <sgarzare@redhat.com>
22  */
24 #include "optionrom.h"
26 #define BOOT_ROM_PRODUCT "PVH loader"
28 #define GS_PROT_JUMP            0
29 #define GS_GDT_DESC             6
31 #ifdef OPTION_ROM_START
32 #undef OPTION_ROM_START
33 #endif
34 #ifdef OPTION_ROM_END
35 #undef OPTION_ROM_END
36 #endif
39  * Redefine OPTION_ROM_START and OPTION_ROM_END, because this rom is produced
40  * linking multiple objects.
41  * signrom.py will add padding.
42  */
43 #define OPTION_ROM_START                                \
44     .code16;                                            \
45     .text;                                              \
46         .global         _start;                         \
47     _start:;                                            \
48         .short          0xaa55;                         \
49         .byte           3; /* desired size in 512 units */
51 #define OPTION_ROM_END                                  \
52     _end:
54 BOOT_ROM_START
56 run_pvhboot:
58         cli
59         cld
61         mov             %cs, %eax
62         shl             $0x4, %eax
64         /* set up a long jump descriptor that is PC relative */
66         /* move stack memory to %gs */
67         mov             %ss, %ecx
68         shl             $0x4, %ecx
69         mov             %esp, %ebx
70         add             %ebx, %ecx
71         sub             $0x20, %ecx
72         sub             $0x30, %esp
73         shr             $0x4, %ecx
74         mov             %cx, %gs
76         /* now push the indirect jump descriptor there */
77         mov             (prot_jump), %ebx
78         add             %eax, %ebx
79         movl            %ebx, %gs:GS_PROT_JUMP
80         mov             $8, %bx
81         movw            %bx, %gs:GS_PROT_JUMP + 4
83         /* fix the gdt descriptor to be PC relative */
84         movw            (gdt_desc), %bx
85         movw            %bx, %gs:GS_GDT_DESC
86         movl            (gdt_desc+2), %ebx
87         add             %eax, %ebx
88         movl            %ebx, %gs:GS_GDT_DESC + 2
90         /* initialize HVM memmap table using int 0x15(e820) */
92         /* ES = pvh_e820 struct */
93         mov             $pvh_e820, %eax
94         shr             $4, %eax
95         mov             %ax, %es
97         /* start storing memmap table at %es:8 (pvh_e820.table) */
98         mov             $8,%edi
99         xor             %ebx, %ebx
100         jmp             memmap_loop
102 memmap_loop_check:
103         /* pvh_e820 can contains up to 128 entries */
104         cmp             $128, %ebx
105         je              memmap_done
107 memmap_loop:
108         /* entry size (hvm_memmap_table_entry) & max buffer size (int15) */
109         movl            $24, %ecx
110         /* e820 */
111         movl            $0x0000e820, %eax
112         /* 'SMAP' magic */
113         movl            $0x534d4150, %edx
114         /* store counter value at %es:0 (pvh_e820.entries) */
115         movl            %ebx, %es:0
117         int             $0x15
118         /* error or last entry already done? */
119         jb              memmap_err
121         /* %edi += entry size (hvm_memmap_table_entry) */
122         add             $24, %edi
124         /* continuation value 0 means last entry */
125         test            %ebx, %ebx
126         jnz             memmap_loop_check
128         /* increase pvh_e820.entries to save the last entry */
129         movl            %es:0, %ebx
130         inc             %ebx
132 memmap_done:
133         movl            %ebx, %es:0
135 memmap_err:
137         /* load the GDT before going into protected mode */
138 lgdt:
139         data32 lgdt     %gs:GS_GDT_DESC
141         /* get us to protected mode now */
142         movl            $1, %eax
143         movl            %eax, %cr0
145         /* the LJMP sets CS for us and gets us to 32-bit */
146 ljmp:
147         data32 ljmp     *%gs:GS_PROT_JUMP
149 prot_mode:
150 .code32
152         /* initialize all other segments */
153         movl            $0x10, %eax
154         movl            %eax, %ss
155         movl            %eax, %ds
156         movl            %eax, %es
157         movl            %eax, %fs
158         movl            %eax, %gs
160         jmp pvh_load_kernel
162 /* Variables */
163 .align 4, 0
164 prot_jump:      .long prot_mode
165                 .short 8
167 .align 4, 0
168 gdt:
169         /* 0x00 */
170 .byte   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
172         /*
173          * 0x08: code segment
174          * (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k)
175          */
176 .byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00
178         /*
179          * 0x10: data segment
180          * (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k)
181          */
182 .byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00
184         /*
185          * 0x18: code segment
186          * (base=0, limit=0x0ffff, type=16bit code exec/read/conf, DPL=0, 1b)
187          */
188 .byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00
190         /*
191          * 0x20: data segment
192          * (base=0, limit=0x0ffff, type=16bit data read/write, DPL=0, 1b)
193          */
194 .byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00
196 gdt_desc:
197 .short  (5 * 8) - 1
198 .long   gdt
200 BOOT_ROM_END