1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22asm (".code32");
23
24#include <stddef.h>
25#include <stdint.h>
26#include "optrom.h"
27#include "optrom_fw_cfg.h"
28#include "../../include/hw/xen/start_info.h"
29
30#define RSDP_SIGNATURE 0x2052545020445352LL
31#define RSDP_AREA_ADDR 0x000E0000
32#define RSDP_AREA_SIZE 0x00020000
33#define EBDA_BASE_ADDR 0x0000040E
34#define EBDA_SIZE 1024
35
36#define E820_MAXENTRIES 128
37#define CMDLINE_BUFSIZE 4096
38
39
40struct pvh_e820_table {
41 uint32_t entries;
42 uint32_t reserved;
43 struct hvm_memmap_table_entry table[E820_MAXENTRIES];
44};
45
46struct pvh_e820_table pvh_e820 asm("pvh_e820") __attribute__ ((aligned));
47
48static struct hvm_start_info start_info;
49static struct hvm_modlist_entry ramdisk_mod;
50static uint8_t cmdline_buffer[CMDLINE_BUFSIZE];
51
52
53
54static uintptr_t search_rsdp(uint32_t start_addr, uint32_t end_addr)
55{
56 uint64_t *rsdp_p;
57
58
59 for (rsdp_p = (uint64_t *)start_addr; rsdp_p < (uint64_t *)end_addr;
60 rsdp_p += 2) {
61 if (*rsdp_p == RSDP_SIGNATURE) {
62 return (uintptr_t)rsdp_p;
63 }
64 }
65
66 return 0;
67}
68
69
70extern void pvh_load_kernel(void) asm("pvh_load_kernel");
71
72void pvh_load_kernel(void)
73{
74 void *cmdline_addr = &cmdline_buffer;
75 void *kernel_entry, *initrd_addr;
76 uint32_t cmdline_size, initrd_size, fw_cfg_version = bios_cfg_version();
77
78 start_info.magic = XEN_HVM_START_MAGIC_VALUE;
79 start_info.version = 1;
80
81
82
83
84
85 start_info.memmap_entries = pvh_e820.entries;
86 start_info.memmap_paddr = (uintptr_t)pvh_e820.table;
87
88
89
90
91
92 start_info.rsdp_paddr = search_rsdp(RSDP_AREA_ADDR,
93 RSDP_AREA_ADDR + RSDP_AREA_SIZE);
94
95
96 if (!start_info.rsdp_paddr) {
97
98
99
100
101 uint32_t ebda_paddr = ((uint32_t)*((uint16_t *)EBDA_BASE_ADDR)) << 4;
102 if (ebda_paddr > 0x400) {
103 uint32_t *ebda = (uint32_t *)ebda_paddr;
104
105 start_info.rsdp_paddr = search_rsdp(*ebda, *ebda + EBDA_SIZE);
106 }
107 }
108
109 bios_cfg_read_entry(&cmdline_size, FW_CFG_CMDLINE_SIZE, 4, fw_cfg_version);
110 bios_cfg_read_entry(cmdline_addr, FW_CFG_CMDLINE_DATA, cmdline_size,
111 fw_cfg_version);
112 start_info.cmdline_paddr = (uintptr_t)cmdline_addr;
113
114
115 bios_cfg_read_entry(&initrd_size, FW_CFG_INITRD_SIZE, 4, fw_cfg_version);
116 if (initrd_size) {
117 bios_cfg_read_entry(&initrd_addr, FW_CFG_INITRD_ADDR, 4,
118 fw_cfg_version);
119 bios_cfg_read_entry(initrd_addr, FW_CFG_INITRD_DATA, initrd_size,
120 fw_cfg_version);
121
122 ramdisk_mod.paddr = (uintptr_t)initrd_addr;
123 ramdisk_mod.size = initrd_size;
124
125
126 start_info.modlist_paddr = (uintptr_t)&ramdisk_mod;
127 start_info.nr_modules = 1;
128 }
129
130 bios_cfg_read_entry(&kernel_entry, FW_CFG_KERNEL_ENTRY, 4, fw_cfg_version);
131
132 asm volatile("jmp *%1" : : "b"(&start_info), "c"(kernel_entry));
133}
134