diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 141399d..f167784 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,12 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - # TODO: something is wrong with TCC, Multiboot 2 info tag struct size - cc: - - exe: 'gcc' - - exe: 'clang' - - exe: 'tcc' - flags: '--without-multiboot2' + cc: ['gcc', 'clang', 'tcc'] opt: ['', '-O0', '-O3'] steps: - uses: actions/checkout@v2 @@ -25,7 +20,7 @@ jobs: - name: autogen run: ./autogen.sh - name: configure - run: ./configure --enable-tests --enable-tests-python ${{matrix.cc.flags}} CC='${{matrix.cc.exe}}' CFLAGS='${{matrix.opt}}' + run: ./configure --enable-tests --enable-tests-python CC='${{matrix.cc}}' CFLAGS='${{matrix.opt}}' - name: make run: make - name: check diff --git a/.gitignore b/.gitignore index 2e2dbcd..a66693f 100644 --- a/.gitignore +++ b/.gitignore @@ -127,6 +127,7 @@ /tests/test_cmdline_gen.c /tests/test_elf /tests/test_mbr +/tests/test_multiboot2_common_packing /tests/test_multiboot2_header_helpers /tests/test_multiboot2_header_print /tests/test_multiboot2_header_validation diff --git a/ChangeLog b/ChangeLog index e1d7ae7..437e049 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2022-06-12 Alex Kotov + + * include/kernaux/multiboot2.h: Fix on Tiny C Compiler + 2022-06-07 Alex Kotov * include/kernaux/libc.h: Has been split into separate headers diff --git a/include/kernaux/multiboot2.h b/include/kernaux/multiboot2.h index 2324d56..6afa972 100644 --- a/include/kernaux/multiboot2.h +++ b/include/kernaux/multiboot2.h @@ -38,6 +38,10 @@ extern "C" { #define KERNAUX_MULTIBOOT2_HTAG_FLAGS_REQUIRE_CONSOLE (1 << 0) #define KERNAUX_MULTIBOOT2_HTAG_FLAGS_EGA_SUPPORT (1 << 1) +#ifdef __TINYC__ +#pragma pack(push, 1) +#endif + /*********************** * Header common types * ***********************/ @@ -255,21 +259,21 @@ __attribute__((packed)); struct KernAux_Multiboot2_ITag_BootCmdLine { // type = 1 - // size = ? + // size > 8 struct KernAux_Multiboot2_ITagBase base; } __attribute__((packed)); struct KernAux_Multiboot2_ITag_BootLoaderName { // type = 2 - // size = ? + // size > 8 struct KernAux_Multiboot2_ITagBase base; } __attribute__((packed)); struct KernAux_Multiboot2_ITag_Module { // type = 3 - // size = ? + // size > 16 struct KernAux_Multiboot2_ITagBase base; unsigned mod_start : 32; @@ -300,7 +304,7 @@ __attribute__((packed)); struct KernAux_Multiboot2_ITag_MemoryMap { // type = 6 - // size = ? + // size > 16 struct KernAux_Multiboot2_ITagBase base; unsigned entry_size : 32; @@ -324,7 +328,7 @@ __attribute__((packed)); struct KernAux_Multiboot2_ITag_FramebufferInfo { // type = 8 - // size = ? + // size > 31 struct KernAux_Multiboot2_ITagBase base; unsigned long long framebuffer_addr : 64; @@ -339,7 +343,7 @@ __attribute__((packed)); struct KernAux_Multiboot2_ITag_ELFSymbols { // type = 9 - // size = ? + // size > 16 struct KernAux_Multiboot2_ITagBase base; unsigned num : 16; @@ -386,7 +390,7 @@ __attribute__((packed)); struct KernAux_Multiboot2_ITag_SMBIOSTables { // type = 13 - // size = ? + // size > 16 struct KernAux_Multiboot2_ITagBase base; unsigned major : 8; @@ -397,28 +401,28 @@ __attribute__((packed)); struct KernAux_Multiboot2_ITag_ACPIOldRSDP { // type = 14 - // size = ? + // size > 8 struct KernAux_Multiboot2_ITagBase base; } __attribute__((packed)); struct KernAux_Multiboot2_ITag_ACPINewRSDP { // type = 15 - // size = ? + // size > 8 struct KernAux_Multiboot2_ITagBase base; } __attribute__((packed)); struct KernAux_Multiboot2_ITag_NetworkingInfo { // type = 16 - // size = ? + // size > 8 struct KernAux_Multiboot2_ITagBase base; } __attribute__((packed)); struct KernAux_Multiboot2_ITag_EFIMemoryMap { // type = 17 - // size = ? + // size > 16 struct KernAux_Multiboot2_ITagBase base; unsigned descriptor_size : 32; @@ -460,6 +464,10 @@ struct KernAux_Multiboot2_ITag_ImageLoadBasePhysAddr { } __attribute__((packed)); +#ifdef __TINYC__ +#pragma pack(pop) +#endif + /******************** * String functions * ********************/ diff --git a/tests/Makefile.am b/tests/Makefile.am index 98768ed..94c5194 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -103,6 +103,19 @@ test_mbr_LDADD = $(top_builddir)/libkernaux.la test_mbr_SOURCES = test_mbr.c endif +################################## +# test_multiboot2_common_packing # +################################## + +if WITH_MULTIBOOT2 +TESTS += test_multiboot2_common_packing +test_multiboot2_common_packing_LDADD = $(top_builddir)/libkernaux.la +test_multiboot2_common_packing_SOURCES = \ + test_multiboot2_common_packing.c \ + multiboot2_header_example2.h \ + multiboot2_info_example2.h +endif + ################################## # test_multiboot2_header_helpers # ################################## diff --git a/tests/multiboot2_header_example2.h b/tests/multiboot2_header_example2.h index 94516ab..5bcada2 100644 --- a/tests/multiboot2_header_example2.h +++ b/tests/multiboot2_header_example2.h @@ -1,3 +1,7 @@ +#ifdef __TINYC__ +#pragma pack(push, 1) +#endif + static const struct { struct KernAux_Multiboot2_Header multiboot2_header; @@ -163,3 +167,7 @@ static const struct { }, }, }; + +#ifdef __TINYC__ +#pragma pack(pop) +#endif diff --git a/tests/multiboot2_info_example2.h b/tests/multiboot2_info_example2.h index dc18006..f260462 100644 --- a/tests/multiboot2_info_example2.h +++ b/tests/multiboot2_info_example2.h @@ -1,3 +1,7 @@ +#ifdef __TINYC__ +#pragma pack(push, 1) +#endif + static const struct { struct KernAux_Multiboot2_Info multiboot2_info; @@ -365,3 +369,7 @@ static const struct { }, }, }; + +#ifdef __TINYC__ +#pragma pack(pop) +#endif diff --git a/tests/test_multiboot2_common_packing.c b/tests/test_multiboot2_common_packing.c new file mode 100644 index 0000000..d47f271 --- /dev/null +++ b/tests/test_multiboot2_common_packing.c @@ -0,0 +1,166 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include "multiboot2_header_example2.h" +#include "multiboot2_info_example2.h" + +#define HEAD_SIZEOF1(type, inst, size) \ + do { \ + assert(sizeof(struct KernAux_Multiboot2_HTag_##type) == (size)); \ + assert(sizeof(multiboot2_header_example2.tag_##inst) == (size)); \ + } while (0) + +#define HEAD_SIZEOF2(type, inst, size1, size2) \ + do { \ + assert(sizeof(struct KernAux_Multiboot2_HTag_##type) == (size1)); \ + assert(sizeof(multiboot2_header_example2.tag_##inst.tag) == (size1)); \ + assert(sizeof(multiboot2_header_example2.tag_##inst) == (size1) + (size2)); \ + } while (0) + +#define INFO_SIZEOF1(type, inst, size) \ + do { \ + assert(sizeof(struct KernAux_Multiboot2_ITag_##type) == (size)); \ + assert(sizeof(multiboot2_info_example2.tag_##inst) == (size)); \ + } while (0) + +#define INFO_SIZEOF2(type, inst, size1, size2) \ + do { \ + assert(sizeof(struct KernAux_Multiboot2_ITag_##type) == (size1)); \ + assert(sizeof(multiboot2_info_example2.tag_##inst.tag) == (size1)); \ + assert(sizeof(multiboot2_info_example2.tag_##inst) == (size1) + (size2)); \ + } while (0) + +// For flag tags that don't include any data +#define HEAD0(name) \ + do { \ + assert(((uint8_t*)&multiboot2_header_example2.tag_##name) == head); \ + head += 8; \ + } while (0) + +#define HEAD2(name, tag_or_data, align) \ + do { \ + assert(((uint8_t*)&multiboot2_header_example2.tag_##name) == head); \ + head += 8 + (tag_or_data) + (align); \ + } while (0) + +#define HEAD3(name, tag, data, align) \ + do { \ + assert(((uint8_t*)&multiboot2_header_example2.tag_##name) == head); \ + head += 8 + (tag) + (data) + (align); \ + } while (0) + +// For flag tags that don't include any data +#define INFO0(name) \ + do { \ + assert(((uint8_t*)&multiboot2_info_example2.tag_##name) == info); \ + info += 8; \ + } while (0) + +#define INFO2(name, tag_or_data, align) \ + do { \ + assert(((uint8_t*)&multiboot2_info_example2.tag_##name) == info); \ + info += 8 + (tag_or_data) + (align); \ + } while (0) + +#define INFO3(name, tag, data, align) \ + do { \ + assert(((uint8_t*)&multiboot2_info_example2.tag_##name) == info); \ + info += 8 + (tag) + (data) + (align); \ + } while (0) + +int main() +{ + assert(sizeof(struct KernAux_Multiboot2_Header) == 16); + assert(sizeof(struct KernAux_Multiboot2_Info) == 8); + + assert(sizeof(multiboot2_header_example2.multiboot2_header) == 16); + assert(sizeof(multiboot2_info_example2.multiboot2_info) == 8); + + assert(sizeof(struct KernAux_Multiboot2_HTagBase) == 8); + assert(sizeof(struct KernAux_Multiboot2_ITagBase) == 8); + + HEAD_SIZEOF1(None, none, 8 ); + HEAD_SIZEOF2(InfoReq, info_req, 8, 4 * 22 ); + HEAD_SIZEOF1(Addr, addr, 24 ); + HEAD_SIZEOF1(EntryAddr, entry_addr, 12 ); + HEAD_SIZEOF1(Flags, flags, 12 ); + HEAD_SIZEOF1(Framebuffer, framebuffer, 20 ); + HEAD_SIZEOF1(ModuleAlign, module_align, 8 ); + HEAD_SIZEOF1(EFIBootServices, efi_boot_services, 8 ); + HEAD_SIZEOF1(EFII386EntryAddr, efi_i386_entry_addr, 12 ); + HEAD_SIZEOF1(EFIAmd64EntryAddr, efi_amd64_entry_addr, 12 ); + HEAD_SIZEOF1(RelocatableHeader, relocatable_header, 24 ); + + INFO_SIZEOF1(None, none, 8 ); + INFO_SIZEOF2(BootCmdLine, boot_cmd_line, 8, 15 ); + INFO_SIZEOF2(BootLoaderName, boot_loader_name, 8, 22 ); + INFO_SIZEOF2(Module, module1, 16, 17 ); + INFO_SIZEOF2(Module, module2, 16, 17 ); + INFO_SIZEOF1(BasicMemoryInfo, basic_memory_info, 16 ); + INFO_SIZEOF1(BIOSBootDevice, bios_boot_device, 20 ); + INFO_SIZEOF2(MemoryMap, memory_map, 16, 160 - 16); + INFO_SIZEOF1(VBEInfo, vbe_info, 784 ); + INFO_SIZEOF2(FramebufferInfo, framebuffer_info, 31, 8 ); + INFO_SIZEOF2(ELFSymbols, elf_symbols, 16, 420 - 16); + INFO_SIZEOF1(APMTable, apm_table, 28 ); + INFO_SIZEOF1(EFI32bitSystemTablePtr, efi_32bit_system_table_ptr, 12 ); + INFO_SIZEOF1(EFI64bitSystemTablePtr, efi_64bit_system_table_ptr, 16 ); + INFO_SIZEOF2(SMBIOSTables, smbios_tables, 16, 8 ); + INFO_SIZEOF2(ACPIOldRSDP, acpi_old_rsdp, 8, 8 ); + INFO_SIZEOF2(ACPINewRSDP, acpi_new_rsdp, 8, 8 ); + INFO_SIZEOF2(NetworkingInfo, networking_info, 8, 8 ); + INFO_SIZEOF2(EFIMemoryMap, efi_memory_map, 16, 8 ); + INFO_SIZEOF1(EFIBootServicesNotTerminated, efi_boot_services_not_terminated, 8 ); + INFO_SIZEOF1(EFI32bitImageHandlePtr, efi_32bit_image_handle_ptr, 12 ); + INFO_SIZEOF1(EFI64bitImageHandlePtr, efi_64bit_image_handle_ptr, 16 ); + INFO_SIZEOF1(ImageLoadBasePhysAddr, image_load_base_phys_addr, 12 ); + + const uint8_t *head = ((const uint8_t*)&multiboot2_header_example2) + 16; + const uint8_t *info = ((const uint8_t*)&multiboot2_info_example2) + 8; + + // (name, tag, data, align); + HEAD2(info_req, /**/ 4 * 22, 0 ); + HEAD2(addr, 16, /**/ 0 ); + HEAD2(entry_addr, 4, /**/ 4 ); + HEAD2(flags, 4, /**/ 4 ); + HEAD2(framebuffer, 12, /**/ 4 ); + HEAD0(module_align /**/ /**/ /**/ ); + HEAD0(efi_boot_services /**/ /**/ /**/ ); + HEAD2(efi_i386_entry_addr, 4, /**/ 4 ); + HEAD2(efi_amd64_entry_addr, 4, /**/ 4 ); + HEAD2(relocatable_header, 16, /**/ 0 ); + HEAD0(none /**/ /**/ /**/ ); + + // (name, tag, data, align); + INFO2(boot_cmd_line, /**/ 15, 1 ); + INFO2(boot_loader_name, /**/ 22, 2 ); + INFO3(module1, 8, 17, 7 ); + INFO3(module2, 8, 17, 7 ); + INFO2(basic_memory_info, 8, /**/ 0 ); + INFO2(bios_boot_device, 12, /**/ 4 ); + INFO3(memory_map, 8, 160 - 16, 0 ); + INFO2(vbe_info, 776, /**/ 0 ); + INFO3(framebuffer_info, 23, 8, 1 ); + INFO3(elf_symbols, 8, 420 - 16, 4 ); + INFO2(apm_table, 20, /**/ 4 ); + INFO2(efi_32bit_system_table_ptr, 4, /**/ 4 ); + INFO2(efi_64bit_system_table_ptr, 8, /**/ 0 ); + INFO3(smbios_tables, 8, 8, 0 ); + INFO2(acpi_old_rsdp, /**/ 8, 0 ); + INFO2(acpi_new_rsdp, /**/ 8, 0 ); + INFO2(networking_info, /**/ 8, 0 ); + INFO3(efi_memory_map, 8, 8, 0 ); + INFO0(efi_boot_services_not_terminated /**/ /**/ /**/ ); + INFO2(efi_32bit_image_handle_ptr, 4, /**/ 4 ); + INFO2(efi_64bit_image_handle_ptr, 8, /**/ 0 ); + INFO2(image_load_base_phys_addr, 4, /**/ 4 ); + INFO0(none /**/ /**/ /**/ ); + + return 0; +} diff --git a/tests/test_multiboot2_info_helpers.c b/tests/test_multiboot2_info_helpers.c index 3d3230b..b6667e8 100644 --- a/tests/test_multiboot2_info_helpers.c +++ b/tests/test_multiboot2_info_helpers.c @@ -9,6 +9,10 @@ #include "multiboot2_info_example1.h" #include "multiboot2_info_example2.h" +#ifdef __TINYC__ +#pragma pack(push, 1) +#endif + static const struct { struct KernAux_Multiboot2_Info multiboot2_info; struct KernAux_Multiboot2_ITag_None tag_none; @@ -113,6 +117,10 @@ static const struct { }, }; +#ifdef __TINYC__ +#pragma pack(pop) +#endif + int main() { assert(KernAux_Multiboot2_Info_is_valid( diff --git a/tests/test_multiboot2_info_validation.c b/tests/test_multiboot2_info_validation.c index de39ede..0c2158b 100644 --- a/tests/test_multiboot2_info_validation.c +++ b/tests/test_multiboot2_info_validation.c @@ -9,6 +9,10 @@ #include "multiboot2_info_example1.h" #include "multiboot2_info_example2.h" +#ifdef __TINYC__ +#pragma pack(push, 1) +#endif + /************ * Tag_None * ************/ @@ -774,6 +778,10 @@ static const struct { }, }; +#ifdef __TINYC__ +#pragma pack(pop) +#endif + /******** * main * ********/