1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "qemu/osdep.h"
27#include "qemu/error-report.h"
28#include "hw/i386/pc.h"
29#include "cpu.h"
30
31#define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d"
32
33static const int bytes_after_table_footer = 32;
34
35static bool ovmf_flash_parsed;
36static uint8_t *ovmf_table;
37static int ovmf_table_len;
38
39void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size)
40{
41 uint8_t *ptr;
42 QemuUUID guid;
43 int tot_len;
44
45
46 if (ovmf_flash_parsed) {
47 return;
48 }
49
50 ovmf_flash_parsed = true;
51
52 if (flash_size < TARGET_PAGE_SIZE) {
53 return;
54 }
55
56
57
58
59
60
61
62 qemu_uuid_parse(OVMF_TABLE_FOOTER_GUID, &guid);
63 guid = qemu_uuid_bswap(guid);
64 ptr = flash_ptr + flash_size - (bytes_after_table_footer + sizeof(guid));
65 if (!qemu_uuid_is_equal((QemuUUID *)ptr, &guid)) {
66 return;
67 }
68
69
70 ptr -= sizeof(uint16_t);
71 tot_len = le16_to_cpu(*(uint16_t *)ptr) - sizeof(guid) - sizeof(uint16_t);
72
73 if (tot_len < 0 || tot_len > (ptr - flash_ptr)) {
74 error_report("OVMF table has invalid size %d", tot_len);
75 return;
76 }
77
78 if (tot_len == 0) {
79
80 return;
81 }
82
83 ovmf_table = g_malloc(tot_len);
84 ovmf_table_len = tot_len;
85
86
87
88
89
90
91 memcpy(ovmf_table, ptr - tot_len, tot_len);
92 ovmf_table += tot_len;
93}
94
95
96
97
98
99
100
101
102
103
104
105
106bool pc_system_ovmf_table_find(const char *entry, uint8_t **data,
107 int *data_len)
108{
109 uint8_t *ptr = ovmf_table;
110 int tot_len = ovmf_table_len;
111 QemuUUID entry_guid;
112
113 assert(ovmf_flash_parsed);
114
115 if (qemu_uuid_parse(entry, &entry_guid) < 0) {
116 return false;
117 }
118
119 if (!ptr) {
120 return false;
121 }
122
123 entry_guid = qemu_uuid_bswap(entry_guid);
124 while (tot_len >= sizeof(QemuUUID) + sizeof(uint16_t)) {
125 int len;
126 QemuUUID *guid;
127
128
129
130
131
132
133
134 guid = (QemuUUID *)(ptr - sizeof(QemuUUID));
135 len = le16_to_cpu(*(uint16_t *)(ptr - sizeof(QemuUUID) -
136 sizeof(uint16_t)));
137
138
139
140
141
142 if (len < sizeof(QemuUUID) + sizeof(uint16_t)) {
143 return false;
144 } else if (len > tot_len) {
145 return false;
146 }
147
148 ptr -= len;
149 tot_len -= len;
150 if (qemu_uuid_is_equal(guid, &entry_guid)) {
151 if (data) {
152 *data = ptr;
153 }
154 if (data_len) {
155 *data_len = len - sizeof(QemuUUID) - sizeof(uint16_t);
156 }
157 return true;
158 }
159 }
160 return false;
161}
162