libkernaux/src/multiboot2/header_print.c

348 lines
10 KiB
C

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <kernaux/assert.h>
#include <kernaux/generic/display.h>
#include <kernaux/macro.h>
#include <kernaux/multiboot2.h>
#include <stddef.h>
#include <stdint.h>
#define PRINTLN(s) do { KernAux_Display_println(display, s); } while (0)
#define PRINTF(format, ...) \
do { KernAux_Display_printf(display, format, __VA_ARGS__); } while (0)
#define PRINTLNF(format, ...) \
do { KernAux_Display_printlnf(display, format, __VA_ARGS__); } while (0)
#define HEADER(Type) do { \
KERNAUX_ASSERT(tag); \
KERNAUX_ASSERT(display); \
\
if (!KernAux_Multiboot2_HTag_##Type##_is_valid(tag)) { \
PRINTLN("Multiboot 2 header tag // invalid!"); \
} \
\
KERNAUX_CAST_CONST(unsigned long, flags, tag->base.flags); \
KERNAUX_CAST_CONST(unsigned long, size, tag->base.size); \
\
PRINTLN("Multiboot 2 header tag {"); \
PRINTLNF(" u16 type: %u (%s)", \
tag->base.type, \
KernAux_Multiboot2_HTag_to_str(tag->base.type) \
); \
PRINTLNF(" u16 flags: %lu", flags); \
PRINTLNF(" u32 size: %lu", size); \
} while (0)
#define FOOTER do { PRINTLN("}"); } while (0)
void KernAux_Multiboot2_Header_print(
const struct KernAux_Multiboot2_Header *const multiboot2_header,
const KernAux_Display display
) {
KERNAUX_ASSERT(multiboot2_header);
KERNAUX_ASSERT(display);
KERNAUX_CAST_CONST(unsigned long, magic, multiboot2_header->magic);
KERNAUX_CAST_CONST(unsigned long, total_size, multiboot2_header->total_size);
KERNAUX_CAST_CONST(unsigned long, checksum, multiboot2_header->checksum);
PRINTLN("Multiboot 2 header {");
PRINTLNF(" u32 magic: %lu", magic);
PRINTLNF(" u32 arch: %u (%s)",
multiboot2_header->arch,
KernAux_Multiboot2_Header_Arch_to_str(multiboot2_header->arch)
);
PRINTLNF(" u32 size: %lu", total_size);
PRINTLNF(" u32 checksum: %lu", checksum);
PRINTLN("}");
const struct KernAux_Multiboot2_HTagBase *tag_base =
(struct KernAux_Multiboot2_HTagBase*)
KERNAUX_MULTIBOOT2_DATA(multiboot2_header);
while (tag_base <
(struct KernAux_Multiboot2_HTagBase*)
((uint8_t*)multiboot2_header + multiboot2_header->total_size))
{
if (!KernAux_Multiboot2_HTagBase_is_valid(tag_base)) return;
KernAux_Multiboot2_HTagBase_print(tag_base, display);
tag_base = KERNAUX_MULTIBOOT2_HTAG_NEXT(tag_base);
}
}
void KernAux_Multiboot2_HTagBase_print(
const struct KernAux_Multiboot2_HTagBase *const tag_base,
const KernAux_Display display
) {
KERNAUX_ASSERT(tag_base);
KERNAUX_ASSERT(display);
switch (tag_base->type) {
case KERNAUX_MULTIBOOT2_HTAG_NONE:
KernAux_Multiboot2_HTag_None_print(
(struct KernAux_Multiboot2_HTag_None*)tag_base,
display
);
break;
case KERNAUX_MULTIBOOT2_HTAG_INFO_REQ:
KernAux_Multiboot2_HTag_InfoReq_print(
(struct KernAux_Multiboot2_HTag_InfoReq*)tag_base,
display
);
break;
case KERNAUX_MULTIBOOT2_HTAG_ADDR:
KernAux_Multiboot2_HTag_Addr_print(
(struct KernAux_Multiboot2_HTag_Addr*)tag_base,
display
);
break;
case KERNAUX_MULTIBOOT2_HTAG_ENTRY_ADDR:
KernAux_Multiboot2_HTag_EntryAddr_print(
(struct KernAux_Multiboot2_HTag_EntryAddr*)tag_base,
display
);
break;
case KERNAUX_MULTIBOOT2_HTAG_FLAGS:
KernAux_Multiboot2_HTag_Flags_print(
(struct KernAux_Multiboot2_HTag_Flags*)tag_base,
display
);
break;
case KERNAUX_MULTIBOOT2_HTAG_FRAMEBUFFER:
KernAux_Multiboot2_HTag_Framebuffer_print(
(struct KernAux_Multiboot2_HTag_Framebuffer*)tag_base,
display
);
break;
case KERNAUX_MULTIBOOT2_HTAG_MODULE_ALIGN:
KernAux_Multiboot2_HTag_ModuleAlign_print(
(struct KernAux_Multiboot2_HTag_ModuleAlign*)tag_base,
display
);
break;
case KERNAUX_MULTIBOOT2_HTAG_EFI_BOOT_SERVICES:
KernAux_Multiboot2_HTag_EFIBootServices_print(
(struct KernAux_Multiboot2_HTag_EFIBootServices*)tag_base,
display
);
break;
case KERNAUX_MULTIBOOT2_HTAG_EFI_I386_ENTRY_ADDR:
KernAux_Multiboot2_HTag_EFII386EntryAddr_print(
(struct KernAux_Multiboot2_HTag_EFII386EntryAddr*)tag_base,
display
);
break;
case KERNAUX_MULTIBOOT2_HTAG_EFI_AMD64_ENTRY_ADDR:
KernAux_Multiboot2_HTag_EFIAmd64EntryAddr_print(
(struct KernAux_Multiboot2_HTag_EFIAmd64EntryAddr*)tag_base,
display
);
break;
case KERNAUX_MULTIBOOT2_HTAG_RELOCATABLE_HEADER:
KernAux_Multiboot2_HTag_RelocatableHeader_print(
(struct KernAux_Multiboot2_HTag_RelocatableHeader*)tag_base,
display
);
break;
}
}
void KernAux_Multiboot2_HTag_None_print(
const struct KernAux_Multiboot2_HTag_None *const tag,
const KernAux_Display display
) {
HEADER(None);
FOOTER;
}
void KernAux_Multiboot2_HTag_InfoReq_print(
const struct KernAux_Multiboot2_HTag_InfoReq *const tag,
const KernAux_Display display
) {
HEADER(InfoReq);
// Print data:
PRINTLN(" u32 mbi_tag_types[]: [");
const uint32_t *const mbi_tag_types =
(const uint32_t*)KERNAUX_MULTIBOOT2_DATA(tag);
for (
size_t index = 0;
index < (tag->base.size - sizeof(*tag)) / sizeof(uint32_t);
++index
) {
KERNAUX_CAST_CONST(unsigned long, type, mbi_tag_types[index]);
PRINTLNF(" %lu (%s)",
type,
KernAux_Multiboot2_ITag_to_str(type)
);
}
PRINTLN(" ]");
FOOTER;
}
void KernAux_Multiboot2_HTag_Addr_print(
const struct KernAux_Multiboot2_HTag_Addr *const tag,
const KernAux_Display display
) {
HEADER(Addr);
KERNAUX_CAST_CONST(unsigned long, header_addr, tag->header_addr);
KERNAUX_CAST_CONST(unsigned long, load_addr, tag->load_addr);
KERNAUX_CAST_CONST(unsigned long, load_end_addr, tag->load_end_addr);
KERNAUX_CAST_CONST(unsigned long, bss_end_addr, tag->bss_end_addr);
PRINTLNF(" u32 header_addr: %lu", header_addr);
PRINTLNF(" u32 load_addr: %lu", load_addr);
PRINTLNF(" u32 load_end_addr: %lu", load_end_addr);
PRINTLNF(" u32 bss_end_addr: %lu", bss_end_addr);
FOOTER;
}
void KernAux_Multiboot2_HTag_EntryAddr_print(
const struct KernAux_Multiboot2_HTag_EntryAddr *const tag,
const KernAux_Display display
) {
HEADER(EntryAddr);
KERNAUX_CAST_CONST(unsigned long, entry_addr, tag->entry_addr);
PRINTLNF(" u32 entry_addr: %lu", entry_addr);
FOOTER;
}
void KernAux_Multiboot2_HTag_Flags_print(
const struct KernAux_Multiboot2_HTag_Flags *const tag,
const KernAux_Display display
) {
HEADER(Flags);
KERNAUX_CAST_CONST(unsigned long, console_flags, tag->console_flags);
PRINTF(" u32 console_flags: %lu (", console_flags);
static const struct {
uint32_t number;
const char *name;
} flags[] = {
{
.number = KERNAUX_MULTIBOOT2_HTAG_FLAGS_REQUIRE_CONSOLE,
.name = "REQUIRE_CONSOLE",
},
{
.number = KERNAUX_MULTIBOOT2_HTAG_FLAGS_EGA_SUPPORT,
.name = "EGA_SUPPORT",
}
};
bool is_first = true;
for (size_t index = 0; index < sizeof(flags) / sizeof(flags[0]); ++index) {
if (tag->console_flags & flags[index].number) {
if (is_first) {
PRINTLN("");
} else {
PRINTLN(" |");
}
PRINTF(" %s", flags[index].name);
is_first = false;
}
}
if (is_first) {
PRINTLN(")");
} else {
PRINTLN("");
PRINTLN(" )");
}
FOOTER;
}
void KernAux_Multiboot2_HTag_Framebuffer_print(
const struct KernAux_Multiboot2_HTag_Framebuffer *const tag,
const KernAux_Display display
) {
HEADER(Framebuffer);
KERNAUX_CAST_CONST(unsigned long, width, tag->width);
KERNAUX_CAST_CONST(unsigned long, height, tag->height);
KERNAUX_CAST_CONST(unsigned long, depth, tag->depth);
PRINTLNF(" u32 width: %lu", width);
PRINTLNF(" u32 height: %lu", height);
PRINTLNF(" u32 depth: %lu", depth);
FOOTER;
}
void KernAux_Multiboot2_HTag_ModuleAlign_print(
const struct KernAux_Multiboot2_HTag_ModuleAlign *const tag,
const KernAux_Display display
) {
HEADER(ModuleAlign);
FOOTER;
}
void KernAux_Multiboot2_HTag_EFIBootServices_print(
const struct KernAux_Multiboot2_HTag_EFIBootServices *const tag,
const KernAux_Display display
) {
HEADER(EFIBootServices);
FOOTER;
}
void KernAux_Multiboot2_HTag_EFII386EntryAddr_print(
const struct KernAux_Multiboot2_HTag_EFII386EntryAddr *const tag,
const KernAux_Display display
) {
HEADER(EFII386EntryAddr);
KERNAUX_CAST_CONST(unsigned long, entry_addr, tag->entry_addr);
PRINTLNF(" u32 entry_addr: %lu", entry_addr);
FOOTER;
}
void KernAux_Multiboot2_HTag_EFIAmd64EntryAddr_print(
const struct KernAux_Multiboot2_HTag_EFIAmd64EntryAddr *const tag,
const KernAux_Display display
) {
HEADER(EFIAmd64EntryAddr);
KERNAUX_CAST_CONST(unsigned long, entry_addr, tag->entry_addr);
PRINTLNF(" u32 entry_addr: %lu", entry_addr);
FOOTER;
}
void KernAux_Multiboot2_HTag_RelocatableHeader_print(
const struct KernAux_Multiboot2_HTag_RelocatableHeader *const tag,
const KernAux_Display display
) {
HEADER(RelocatableHeader);
KERNAUX_CAST_CONST(unsigned long, min_addr, tag->min_addr);
KERNAUX_CAST_CONST(unsigned long, max_addr, tag->max_addr);
KERNAUX_CAST_CONST(unsigned long, align, tag->align);
PRINTLNF(" u32 min_addr: %lu", min_addr);
PRINTLNF(" u32 max_addr: %lu", max_addr);
PRINTLNF(" u32 align: %lu", align);
FOOTER;
}