Merge remote-tracking branch 'remotes/dgilbert-gitlab/tags/pull-migration-20210726a...
[qemu/armbru.git] / hw / i386 / pc_sysfw_ovmf.c
blobf4dd92c58825f532b341bf0039e98e97e90e8d8d
1 /*
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
23 * THE SOFTWARE.
26 #include "qemu/osdep.h"
27 #include "hw/i386/pc.h"
28 #include "cpu.h"
30 #define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d"
32 static bool ovmf_flash_parsed;
33 static uint8_t *ovmf_table;
34 static int ovmf_table_len;
36 void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size)
38 uint8_t *ptr;
39 QemuUUID guid;
40 int tot_len;
42 /* should only be called once */
43 if (ovmf_flash_parsed) {
44 return;
47 ovmf_flash_parsed = true;
49 if (flash_size < TARGET_PAGE_SIZE) {
50 return;
54 * if this is OVMF there will be a table footer
55 * guid 48 bytes before the end of the flash file. If it's
56 * not found, silently abort the flash parsing.
58 qemu_uuid_parse(OVMF_TABLE_FOOTER_GUID, &guid);
59 guid = qemu_uuid_bswap(guid); /* guids are LE */
60 ptr = flash_ptr + flash_size - 48;
61 if (!qemu_uuid_is_equal((QemuUUID *)ptr, &guid)) {
62 return;
65 /* if found, just before is two byte table length */
66 ptr -= sizeof(uint16_t);
67 tot_len = le16_to_cpu(*(uint16_t *)ptr) - sizeof(guid) - sizeof(uint16_t);
69 if (tot_len <= 0) {
70 return;
73 ovmf_table = g_malloc(tot_len);
74 ovmf_table_len = tot_len;
77 * ptr is the foot of the table, so copy it all to the newly
78 * allocated ovmf_table and then set the ovmf_table pointer
79 * to the table foot
81 memcpy(ovmf_table, ptr - tot_len, tot_len);
82 ovmf_table += tot_len;
85 /**
86 * pc_system_ovmf_table_find - Find the data associated with an entry in OVMF's
87 * reset vector GUIDed table.
89 * @entry: GUID string of the entry to lookup
90 * @data: Filled with a pointer to the entry's value (if not NULL)
91 * @data_len: Filled with the length of the entry's value (if not NULL). Pass
92 * NULL here if the length of data is known.
94 * Return: true if the entry was found in the OVMF table; false otherwise.
96 bool pc_system_ovmf_table_find(const char *entry, uint8_t **data,
97 int *data_len)
99 uint8_t *ptr = ovmf_table;
100 int tot_len = ovmf_table_len;
101 QemuUUID entry_guid;
103 assert(ovmf_flash_parsed);
105 if (qemu_uuid_parse(entry, &entry_guid) < 0) {
106 return false;
109 if (!ptr) {
110 return false;
113 entry_guid = qemu_uuid_bswap(entry_guid); /* guids are LE */
114 while (tot_len >= sizeof(QemuUUID) + sizeof(uint16_t)) {
115 int len;
116 QemuUUID *guid;
119 * The data structure is
120 * arbitrary length data
121 * 2 byte length of entire entry
122 * 16 byte guid
124 guid = (QemuUUID *)(ptr - sizeof(QemuUUID));
125 len = le16_to_cpu(*(uint16_t *)(ptr - sizeof(QemuUUID) -
126 sizeof(uint16_t)));
129 * just in case the table is corrupt, wouldn't want to spin in
130 * the zero case
132 if (len < sizeof(QemuUUID) + sizeof(uint16_t)) {
133 return false;
134 } else if (len > tot_len) {
135 return false;
138 ptr -= len;
139 tot_len -= len;
140 if (qemu_uuid_is_equal(guid, &entry_guid)) {
141 if (data) {
142 *data = ptr;
144 if (data_len) {
145 *data_len = len - sizeof(QemuUUID) - sizeof(uint16_t);
147 return true;
150 return false;