1 /*
2  * Copyright (c) 2024 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include "bootinfo.h"
9 
10 #include <lk/compiler.h>
11 #include <lk/trace.h>
12 #include <lk/debug.h>
13 #include <stdio.h>
14 
15 #define LOCAL_TRACE 0
16 
17 extern uint8_t __bss_end;
18 
bootinfo_tag_to_string(enum BOOTINFO_TAGS tag)19 static const char *bootinfo_tag_to_string(enum BOOTINFO_TAGS tag) {
20     switch (tag) {
21         case BOOTINFO_TAG_END: return "END";
22         case BOOTINFO_TAG_MACHTYPE: return "MACHTYPE";
23         case BOOTINFO_TAG_CPUTYPE: return "CPUTYPE";
24         case BOOTINFO_TAG_FPUTYPE: return "FPUTYPE";
25         case BOOTINFO_TAG_MMUTYPE: return "MMUTYPE";
26         case BOOTINFO_TAG_MEMCHUNK: return "MEMCHUNK";
27         case BOOTINFO_TAG_RAMDISK: return "RAMDISK";
28         case BOOTINFO_TAG_COMMAND_LINE: return "COMMAND_LINE";
29         case BOOTINFO_TAG_RNG_SEED: return "RNG_SEED";
30         case BOOTINFO_TAG_VIRT_QEMU_VERSION: return "VIRT_QEMU_VERSION";
31         case BOOTINFO_TAG_VIRT_GF_PIC_BASE: return "VIRT_GF_PIC_BASE";
32         case BOOTINFO_TAG_VIRT_GF_RTC_BASE: return "VIRT_GF_RTC_BASE";
33         case BOOTINFO_TAG_VIRT_GF_TTY_BASE: return "VIRT_GF_TTY_BASE";
34         case BOOTINFO_TAG_VIRT_VIRTIO_BASE: return "VIRT_VIRTIO_BASE";
35         case BOOTINFO_TAG_VIRT_CTRL_BASE: return "VIRT_CTRL_BASE";
36         default: return "UNKNOWN";
37     }
38 }
39 
dump_bootinfo_record(const struct bootinfo_item * item)40 static void dump_bootinfo_record(const struct bootinfo_item *item) {
41     printf("item %p: tag %hx (%s), size %hu\n", item, item->tag, bootinfo_tag_to_string(item->tag), item->size);
42     if (item->size > 4) {
43         hexdump8(item->data, item->size - 4);
44     }
45 }
46 
dump_all_bootinfo_records(void)47 void dump_all_bootinfo_records(void) {
48     const uint8_t *ptr = &__bss_end;
49 
50     printf("bootinfo records at %p:\n", ptr);
51     for (;;) {
52         const struct bootinfo_item *item = (const struct bootinfo_item *)ptr;
53         if (item->tag == BOOTINFO_TAG_END) {
54             break;
55         }
56 
57         dump_bootinfo_record(item);
58 
59         // move to the next field
60         ptr += item->size;
61     }
62 }
63 
64 // look for tags that qemu left at the end of the kernel that hold various
65 // pieces of system configuration info.
bootinfo_find_record(uint16_t id,uint16_t * size_out)66 const void *bootinfo_find_record(uint16_t id, uint16_t *size_out) {
67     const uint8_t *ptr = &__bss_end;
68 
69     *size_out = 0;
70     for (;;) {
71         const struct bootinfo_item *item = (const struct bootinfo_item *)ptr;
72         if (item->tag == BOOTINFO_TAG_END) {
73             return NULL;
74         }
75 
76         if (LOCAL_TRACE > 2) {
77             dump_bootinfo_record(item);
78         }
79 
80         if (item->tag == id) {
81             *size_out = item->size - 4;
82             return item->data;
83         } else if (item->tag == 0) { // end token
84             return NULL;
85         }
86 
87         // move to the next field
88         ptr += item->size;
89     }
90 }
91 
92