aboutsummaryrefslogtreecommitdiffstats
path: root/roms/qboot/tables.c
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/qboot/tables.c
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/qboot/tables.c')
-rw-r--r--roms/qboot/tables.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/roms/qboot/tables.c b/roms/qboot/tables.c
new file mode 100644
index 000000000..9934a913a
--- /dev/null
+++ b/roms/qboot/tables.c
@@ -0,0 +1,159 @@
+#include "bios.h"
+#include "stdio.h"
+#include "fw_cfg.h"
+#include "string.h"
+#include "start_info.h"
+
+extern struct hvm_start_info start_info;
+
+struct loader_cmd {
+ uint32_t cmd;
+ union {
+#define CMD_QUIT 0
+#define CMD_ALLOC 1
+ struct {
+ char file[56];
+ uint32_t align;
+ uint8_t zone;
+ } alloc;
+#define CMD_PTR 2
+ struct {
+ char dest[56];
+ char src[56];
+ uint32_t offset;
+ uint8_t size;
+ } ptr;
+#define CMD_CHECKSUM 3
+ struct {
+ char file[56];
+ uint32_t offset;
+ uint32_t start;
+ uint32_t len;
+ } checksum;
+ uint8_t pad[124];
+ };
+} __attribute__((__packed__));
+
+enum {
+ ALLOC_HIGH = 1,
+ ALLOC_FSEG = 2
+};
+
+static uint8_t *file_address[20];
+
+static inline void *id_to_addr(int fw_cfg_id)
+{
+ return file_address[fw_cfg_id];
+}
+
+static inline void set_file_addr(int fw_cfg_id, void *p)
+{
+ file_address[fw_cfg_id] = p;
+}
+
+static void do_alloc(char *file, uint32_t align, uint8_t zone)
+{
+ int id = fw_cfg_file_id(file);
+ int n = fw_cfg_file_size(id);
+ char *p;
+
+ if (id == -1)
+ panic();
+
+ if (align < 16)
+ align = 16;
+
+ if (zone == ALLOC_FSEG)
+ p = malloc_fseg_align(n, align);
+ else
+ p = malloc_align(n, align);
+
+ set_file_addr(id, p);
+ fw_cfg_read_file(id, p, n);
+
+ /* For PVH boot, save the PA where the RSDP is stored */
+ if (zone == ALLOC_FSEG) {
+ if (!memcmp(p, "RSD PTR ", 8)) {
+ start_info.rsdp_paddr = (uintptr_t)id_to_addr(id);
+ }
+ }
+}
+
+static void do_ptr(char *dest, char *src, uint32_t offset, uint8_t size)
+{
+ char *p, *q;
+ int id;
+ union {
+ long long ll;
+ char b[8];
+ } data;
+
+ id = fw_cfg_file_id(src);
+ p = id_to_addr(id);
+ if (!p)
+ panic();
+
+ id = fw_cfg_file_id(dest);
+ q = id_to_addr(id);
+ if (!q)
+ panic();
+
+ q += offset;
+
+ /* Assumes little endian */
+ data.ll = 0;
+ memcpy(&data.b, q, size);
+ data.ll += (uintptr_t) p;
+ memcpy(q, &data.b, size);
+}
+
+static void do_checksum(char *file, uint32_t offset, uint32_t start, uint32_t len)
+{
+ uint8_t *p;
+ int id;
+ int n;
+
+ id = fw_cfg_file_id(file);
+ p = id_to_addr(id);
+ if (!p)
+ panic();
+
+ n = fw_cfg_file_size(id);
+ if (offset >= n || n < start || len > n - start)
+ panic();
+
+ p[offset] -= csum8(&p[start], len);
+}
+
+void extract_acpi(void)
+{
+ int id = fw_cfg_file_id("etc/table-loader");
+ int n = fw_cfg_file_size(id);
+ struct loader_cmd script[n / sizeof(struct loader_cmd)];
+ int i;
+
+ if (!n)
+ return;
+
+ fw_cfg_read_file(id, script, n);
+
+ for (i = 0; i < ARRAY_SIZE(script); i++) {
+ struct loader_cmd *s = &script[i];
+ switch(script[i].cmd) {
+ case CMD_ALLOC:
+ do_alloc(s->alloc.file, s->alloc.align, s->alloc.zone);
+ break;
+ case CMD_PTR:
+ do_ptr(s->ptr.dest, s->ptr.src, s->ptr.offset, s->ptr.size);
+ break;
+ case CMD_CHECKSUM:
+ do_checksum(s->checksum.file, s->checksum.offset,
+ s->checksum.start, s->checksum.len);
+ break;
+ case CMD_QUIT:
+ return;
+ default:
+ panic();
+ }
+ }
+}