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 */ 23 24#include "optionrom.h" 25 26#define BOOT_ROM_PRODUCT "PVH loader" 27 28#define GS_PROT_JUMP 0 29#define GS_GDT_DESC 6 30 31#ifdef OPTION_ROM_START 32#undef OPTION_ROM_START 33#endif 34#ifdef OPTION_ROM_END 35#undef OPTION_ROM_END 36#endif 37 38/* 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 */ 50 51#define OPTION_ROM_END \ 52 _end: 53 54BOOT_ROM_START 55 56run_pvhboot: 57 58 cli 59 cld 60 61 mov %cs, %eax 62 shl $0x4, %eax 63 64 /* set up a long jump descriptor that is PC relative */ 65 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 75 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 82 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 89 90 /* initialize HVM memmap table using int 0x15(e820) */ 91 92 /* ES = pvh_e820 struct */ 93 mov $pvh_e820, %eax 94 shr $4, %eax 95 mov %ax, %es 96 97 /* start storing memmap table at %es:8 (pvh_e820.table) */ 98 mov $8,%edi 99 xor %ebx, %ebx 100 jmp memmap_loop 101 102memmap_loop_check: 103 /* pvh_e820 can contains up to 128 entries */ 104 cmp $128, %ebx 105 je memmap_done 106 107memmap_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 116 117 int $0x15 118 /* error or last entry already done? */ 119 jb memmap_err 120 121 /* %edi += entry size (hvm_memmap_table_entry) */ 122 add $24, %edi 123 124 /* continuation value 0 means last entry */ 125 test %ebx, %ebx 126 jnz memmap_loop_check 127 128 /* increase pvh_e820.entries to save the last entry */ 129 movl %es:0, %ebx 130 inc %ebx 131 132memmap_done: 133 movl %ebx, %es:0 134 135memmap_err: 136 137 /* load the GDT before going into protected mode */ 138lgdt: 139 data32 lgdt %gs:GS_GDT_DESC 140 141 /* get us to protected mode now */ 142 movl $1, %eax 143 movl %eax, %cr0 144 145 /* the LJMP sets CS for us and gets us to 32-bit */ 146ljmp: 147 data32 ljmp *%gs:GS_PROT_JUMP 148 149prot_mode: 150.code32 151 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 159 160 jmp pvh_load_kernel 161 162/* Variables */ 163.align 4, 0 164prot_jump: .long prot_mode 165 .short 8 166 167.align 4, 0 168gdt: 169 /* 0x00 */ 170.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 171 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 177 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 183 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 189 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 195 196gdt_desc: 197.short (5 * 8) - 1 198.long gdt 199 200BOOT_ROM_END 201