2 * QEMU PC System Firmware (OVMF specific)
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 * Copyright (c) 2011-2012 Intel Corporation
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #include "qemu/osdep.h"
27 #include "qemu/error-report.h"
28 #include "hw/i386/pc.h"
31 #define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d"
33 static const int bytes_after_table_footer
= 32;
35 static bool ovmf_flash_parsed
;
36 static uint8_t *ovmf_table
;
37 static int ovmf_table_len
;
39 void pc_system_parse_ovmf_flash(uint8_t *flash_ptr
, size_t flash_size
)
45 /* should only be called once */
46 if (ovmf_flash_parsed
) {
50 ovmf_flash_parsed
= true;
52 if (flash_size
< TARGET_PAGE_SIZE
) {
57 * if this is OVMF there will be a table footer
58 * guid 48 bytes before the end of the flash file
59 * (= 32 bytes after the table + 16 bytes the GUID itself).
60 * If it's not found, silently abort the flash parsing.
62 qemu_uuid_parse(OVMF_TABLE_FOOTER_GUID
, &guid
);
63 guid
= qemu_uuid_bswap(guid
); /* guids are LE */
64 ptr
= flash_ptr
+ flash_size
- (bytes_after_table_footer
+ sizeof(guid
));
65 if (!qemu_uuid_is_equal((QemuUUID
*)ptr
, &guid
)) {
69 /* if found, just before is two byte table length */
70 ptr
-= sizeof(uint16_t);
71 tot_len
= le16_to_cpu(*(uint16_t *)ptr
) - sizeof(guid
) - sizeof(uint16_t);
73 if (tot_len
< 0 || tot_len
> (ptr
- flash_ptr
)) {
74 error_report("OVMF table has invalid size %d", tot_len
);
79 /* no entries in the OVMF table */
83 ovmf_table
= g_malloc(tot_len
);
84 ovmf_table_len
= tot_len
;
87 * ptr is the foot of the table, so copy it all to the newly
88 * allocated ovmf_table and then set the ovmf_table pointer
91 memcpy(ovmf_table
, ptr
- tot_len
, tot_len
);
92 ovmf_table
+= tot_len
;
96 * pc_system_ovmf_table_find - Find the data associated with an entry in OVMF's
97 * reset vector GUIDed table.
99 * @entry: GUID string of the entry to lookup
100 * @data: Filled with a pointer to the entry's value (if not NULL)
101 * @data_len: Filled with the length of the entry's value (if not NULL). Pass
102 * NULL here if the length of data is known.
104 * Return: true if the entry was found in the OVMF table; false otherwise.
106 bool pc_system_ovmf_table_find(const char *entry
, uint8_t **data
,
109 uint8_t *ptr
= ovmf_table
;
110 int tot_len
= ovmf_table_len
;
113 assert(ovmf_flash_parsed
);
115 if (qemu_uuid_parse(entry
, &entry_guid
) < 0) {
123 entry_guid
= qemu_uuid_bswap(entry_guid
); /* guids are LE */
124 while (tot_len
>= sizeof(QemuUUID
) + sizeof(uint16_t)) {
129 * The data structure is
130 * arbitrary length data
131 * 2 byte length of entire entry
134 guid
= (QemuUUID
*)(ptr
- sizeof(QemuUUID
));
135 len
= le16_to_cpu(*(uint16_t *)(ptr
- sizeof(QemuUUID
) -
139 * just in case the table is corrupt, wouldn't want to spin in
142 if (len
< sizeof(QemuUUID
) + sizeof(uint16_t)) {
144 } else if (len
> tot_len
) {
150 if (qemu_uuid_is_equal(guid
, &entry_guid
)) {
155 *data_len
= len
- sizeof(QemuUUID
) - sizeof(uint16_t);