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