diff --git a/.gitignore b/.gitignore index 28708de..ef926c4 100644 --- a/.gitignore +++ b/.gitignore @@ -113,6 +113,7 @@ /examples/macro_container_of /examples/macro_packing /examples/memmap +/examples/multiboot2_header_macro /examples/ntoa /examples/panic /examples/pfa diff --git a/README.md b/README.md index c0be2cf..469571c 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ zero). Work-in-progress APIs can change at any time. * [ELF](/include/kernaux/elf.h) (*work in progress*) * [MBR](/include/kernaux/mbr.h) (*work in progress*) * [Multiboot 2 (GRUB 2)](/include/kernaux/multiboot2.h.in) (*work in progress*) + * [Example: header macros](/examples/multiboot2_header_macro.c) * Utilities * [Measurement units utils](/include/kernaux/units.h) (*work in progress*) * [Example: To human](/examples/units_human.c) diff --git a/examples/Makefile.am b/examples/Makefile.am index 550b7eb..3fda5ce 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -71,6 +71,16 @@ memmap_LDADD = $(top_builddir)/libkernaux.la memmap_SOURCES = main.c memmap.c endif +########################### +# multiboot2_header_macro # +########################### + +if WITH_MULTIBOOT2 +TESTS += multiboot2_header_macro +multiboot2_header_macro_LDADD = $(top_builddir)/libkernaux.la +multiboot2_header_macro_SOURCES = main.c multiboot2_header_macro.c +endif + ######## # ntoa # ######## diff --git a/examples/multiboot2_header_macro.c b/examples/multiboot2_header_macro.c new file mode 100644 index 0000000..57e2542 --- /dev/null +++ b/examples/multiboot2_header_macro.c @@ -0,0 +1,97 @@ +#include + +#include + +#include + +__attribute__((aligned(KERNAUX_MULTIBOOT2_HEADER_ALIGN))) +static const struct { + struct KernAux_Multiboot2_Header header; + // This macro may be used to create the tag + // of type "KernAux_Multiboot2_HTag_InfoReq" + // when the number of requested information + // tag types is even (n % 2 == 0). + KERNAUX_MULTIBOOT2_HFIELDS_INFO_REQ_EVEN( + // This is the name of the structure field. + tag_info_req_even, + // This is the number of requested information tag types. + // IT MUST BE EVEN!!! (n % 2 == 0) + 2 + ) + // This macro may be used to create the tag + // of type "KernAux_Multiboot2_HTag_InfoReq" + // when the number of requested information + // tag types is odd (n % 2 == 1). + KERNAUX_MULTIBOOT2_HFIELDS_INFO_REQ_ODD( + // This is the name of the structure field. + tag_info_req_odd, + // This is the number of requested information tag types. + // IT MUST BE ODD!!! (n % 2 == 1) + 1, + // This is the name of the additional structure field + // which will be used to align the following tags properly. + // You may keep it unassigned. + _align1 + ) + // This macro may be used for all other header tag types. + KERNAUX_MULTIBOOT2_HFIELDS_COMMON( + // This is the name of the structure field. + tag_none, + // This is the type of the structure field + // without the "KernAux_Multiboot2_HTag_" prefix. + None + ) +} +KERNAUX_PACKED +multiboot2_header = { + .header = { + .magic = KERNAUX_MULTIBOOT2_HEADER_MAGIC, + .arch = KERNAUX_MULTIBOOT2_HEADER_ARCH_I386, + .total_size = sizeof(multiboot2_header), + .checksum = KERNAUX_MULTIBOOT2_HEADER_CHECKSUM( + KERNAUX_MULTIBOOT2_HEADER_ARCH_I386, + sizeof(multiboot2_header) + ), + }, + .tag_info_req_even = { + .tag = { + .base = { + .type = KERNAUX_MULTIBOOT2_HTAG_INFO_REQ, + .flags = KERNAUX_MULTIBOOT2_HTAG_BASE_FLAG_OPTIONAL, + .size = sizeof(multiboot2_header.tag_info_req_even), + }, + }, + .mbi_tag_types = { + KERNAUX_MULTIBOOT2_ITAG_BOOT_CMD_LINE, + KERNAUX_MULTIBOOT2_ITAG_BOOT_LOADER_NAME, + }, + }, + .tag_info_req_odd = { + .tag = { + .base = { + .type = KERNAUX_MULTIBOOT2_HTAG_INFO_REQ, + .flags = KERNAUX_MULTIBOOT2_HTAG_BASE_FLAG_OPTIONAL, + .size = sizeof(multiboot2_header.tag_info_req_odd), + }, + }, + .mbi_tag_types = { + KERNAUX_MULTIBOOT2_ITAG_ELF_SYMBOLS, + }, + }, + .tag_none = { + .tag = { + .base = { + .type = KERNAUX_MULTIBOOT2_HTAG_NONE, + .flags = 0, + .size = sizeof(multiboot2_header.tag_none), + }, + }, + }, +}; + +#include + +void example_main() +{ + assert(KernAux_Multiboot2_Header_is_valid(&multiboot2_header.header)); +} diff --git a/include/Makefile.am b/include/Makefile.am index 5e738e4..bce1eb0 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -70,7 +70,9 @@ if WITH_MEMMAP nobase_include_HEADERS += kernaux/memmap.h endif if WITH_MULTIBOOT2 -nobase_include_HEADERS += kernaux/multiboot2.h +nobase_include_HEADERS += \ + kernaux/multiboot2.h \ + kernaux/multiboot2/header_macro.h endif if WITH_NTOA nobase_include_HEADERS += kernaux/ntoa.h diff --git a/include/kernaux.h.in b/include/kernaux.h.in index e1fe0ff..3090a5d 100644 --- a/include/kernaux.h.in +++ b/include/kernaux.h.in @@ -20,6 +20,7 @@ @comment_line_mbr@#include @comment_line_memmap@#include @comment_line_multiboot2@#include +@comment_line_multiboot2@#include @comment_line_ntoa@#include @comment_line_pfa@#include @comment_line_printf@#include diff --git a/include/kernaux/multiboot2.h.in b/include/kernaux/multiboot2.h.in index 660b193..b2b8f14 100644 --- a/include/kernaux/multiboot2.h.in +++ b/include/kernaux/multiboot2.h.in @@ -7,6 +7,7 @@ extern "C" { #include @comment_line_memmap@#include +#include #include #include diff --git a/include/kernaux/multiboot2/header_macro.h b/include/kernaux/multiboot2/header_macro.h new file mode 100644 index 0000000..83bd1b6 --- /dev/null +++ b/include/kernaux/multiboot2/header_macro.h @@ -0,0 +1,39 @@ +#ifndef KERNAUX_INCLUDED_MULTIBOOT2_HEADER_MACRO +#define KERNAUX_INCLUDED_MULTIBOOT2_HEADER_MACRO + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include + +#define KERNAUX_MULTIBOOT2_HFIELDS_COMMON(name, type) \ + struct { \ + struct KernAux_Multiboot2_HTag_##type tag; \ + } KERNAUX_PACKED name; + +#define KERNAUX_MULTIBOOT2_HFIELDS_INFO_REQ_ODD( \ + name, mbi_tag_types_count, align_name \ +) \ + struct { \ + struct KernAux_Multiboot2_HTag_InfoReq tag; \ + uint32_t mbi_tag_types[mbi_tag_types_count]; \ + } KERNAUX_PACKED name; \ + uint8_t align_name[4]; + +#define KERNAUX_MULTIBOOT2_HFIELDS_INFO_REQ_EVEN( \ + name, mbi_tag_types_count \ +) \ + struct { \ + struct KernAux_Multiboot2_HTag_InfoReq tag; \ + uint32_t mbi_tag_types[mbi_tag_types_count]; \ + } KERNAUX_PACKED name; + +#ifdef __cplusplus +} +#endif + +#endif