mirror of
				https://github.com/tailix/libkernaux.git
				synced 2025-10-30 23:47:50 -04:00 
			
		
		
		
	
							parent
							
								
									1e749c5c89
								
							
						
					
					
						commit
						af165909db
					
				
					 19 changed files with 876 additions and 3 deletions
				
			
		
							
								
								
									
										1
									
								
								.github/workflows/main.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/main.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -94,6 +94,7 @@ jobs: | |||
|           - without: 'ntoa' | ||||
|             dependencies: '--without-printf --without-units' | ||||
|           - without: 'printf' | ||||
|           - without: 'memmap' | ||||
|     steps: | ||||
|       - uses: actions/checkout@v2 | ||||
|       - name: autogen | ||||
|  |  | |||
							
								
								
									
										10
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								ChangeLog
									
										
									
									
									
								
							|  | @ -1,7 +1,11 @@ | |||
| 2023-01-06  Alex Kotov  <kotovalexarian@gmail.com> | ||||
| 2023-01-04  Alex Kotov  <kotovalexarian@gmail.com> | ||||
| 
 | ||||
| 	* configure.ac: Package "--with[out]-memmap" has been removed | ||||
| 	* include/kernaux/memmap.h: The header has been removed | ||||
| 	* include/kernaux/memmap.h: The function "KernAux_Memmap_Builder_add" has been | ||||
| 	changed. | ||||
| 	* include/kernaux/multiboot2.h: The function | ||||
| 	"KernAux_Multiboot2_Info_to_memmap_builder" has been renamed to | ||||
| 	"KernAux_Multiboot2_Info_build_memmap_from_memmap", it's signature has been | ||||
| 	changed. | ||||
| 
 | ||||
| 2022-12-27  Alex Kotov  <kotovalexarian@gmail.com> | ||||
| 
 | ||||
|  |  | |||
|  | @ -77,12 +77,16 @@ endif | |||
| if WITH_MBR | ||||
| libkernaux_la_SOURCES += src/mbr.c | ||||
| endif | ||||
| if WITH_MEMMAP | ||||
| libkernaux_la_SOURCES += src/memmap.c | ||||
| endif | ||||
| if WITH_MULTIBOOT2 | ||||
| libkernaux_la_SOURCES += \ | ||||
| 	src/multiboot2/header_enums.c \ | ||||
| 	src/multiboot2/header_helpers.c \ | ||||
| 	src/multiboot2/header_is_valid.c \ | ||||
| 	src/multiboot2/header_print.c \ | ||||
| 	src/multiboot2/info_convert.c \ | ||||
| 	src/multiboot2/info_enums.c \ | ||||
| 	src/multiboot2/info_helpers.c \ | ||||
| 	src/multiboot2/info_is_valid.c \ | ||||
|  |  | |||
|  | @ -69,6 +69,8 @@ zero). Work-in-progress APIs can change at any time. | |||
| * Utilities | ||||
|   * [Measurement units utils](/include/kernaux/units.h) (*work in progress*) | ||||
|     * [Example: To human](/examples/units_human.c) | ||||
|   * [Memory map](/include/kernaux/memmap.h) (*non-breaking since* **?.?.?**) | ||||
|     * [Example](/examples/memmap.c) | ||||
|   * [printf format parser](/include/kernaux/printf_fmt.h) (*non-breaking since* **0.6.0**) | ||||
|     * [Example](/examples/printf_fmt.c) | ||||
| * Usual functions | ||||
|  | @ -153,6 +155,7 @@ explicitly included, use `--without-all`. | |||
| * `--with[out]-asm` - kernel assembler helpers | ||||
| * `--with[out]-cmdline` - command line parser | ||||
| * `--with[out]-free-list` - free list memory allocator | ||||
| * `--with[out]-memmap` - memory map | ||||
| * `--with[out]-multiboot2` - Multiboot 2 utils | ||||
| * `--with[out]-ntoa` - itoa/ftoa | ||||
| * `--with[out]-printf` - printf | ||||
|  |  | |||
|  | @ -75,6 +75,7 @@ AC_ARG_WITH(  [cmdline],         AS_HELP_STRING([--without-cmdline],        [wit | |||
| AC_ARG_WITH(  [elf],             AS_HELP_STRING([--without-elf],            [without ELF utils])) | ||||
| AC_ARG_WITH(  [free-list],       AS_HELP_STRING([--without-free-list],      [without free list memory allocator])) | ||||
| AC_ARG_WITH(  [mbr],             AS_HELP_STRING([--without-mbr],            [without MBR utils])) | ||||
| AC_ARG_WITH(  [memmap],          AS_HELP_STRING([--without-memmap],         [without memory map])) | ||||
| AC_ARG_WITH(  [multiboot2],      AS_HELP_STRING([--without-multiboot2],     [without Multiboot 2 utils])) | ||||
| AC_ARG_WITH(  [ntoa],            AS_HELP_STRING([--without-ntoa],           [without itoa/ftoa])) | ||||
| AC_ARG_WITH(  [pfa],             AS_HELP_STRING([--without-pfa],            [without Page Frame Allocator])) | ||||
|  | @ -115,6 +116,7 @@ if test -z "$with_cmdline";      then with_cmdline=no;      fi | |||
| if test -z "$with_elf";          then with_elf=no;          fi | ||||
| if test -z "$with_free_list";    then with_free_list=no;    fi | ||||
| if test -z "$with_mbr";          then with_mbr=no;          fi | ||||
| if test -z "$with_memmap";       then with_memmap=no;       fi | ||||
| if test -z "$with_multiboot2";   then with_multiboot2=no;   fi | ||||
| if test -z "$with_ntoa";         then with_ntoa=no;         fi | ||||
| if test -z "$with_pfa";          then with_pfa=no;          fi | ||||
|  | @ -159,6 +161,7 @@ AS_IF([test "$with_cmdline"           = no ], [with_cmdline=no],            [wit | |||
| AS_IF([test "$with_elf"               = no ], [with_elf=no],                [with_elf=yes]) | ||||
| AS_IF([test "$with_free_list"         = no ], [with_free_list=no],          [with_free_list=yes]) | ||||
| AS_IF([test "$with_mbr"               = no ], [with_mbr=no],                [with_mbr=yes]) | ||||
| AS_IF([test "$with_memmap"            = no ], [with_memmap=no],             [with_memmap=yes]) | ||||
| AS_IF([test "$with_multiboot2"        = no ], [with_multiboot2=no],         [with_multiboot2=yes]) | ||||
| AS_IF([test "$with_ntoa"              = no ], [with_ntoa=no],               [with_ntoa=yes]) | ||||
| AS_IF([test "$with_pfa"               = no ], [with_pfa=no],                [with_pfa=yes]) | ||||
|  | @ -218,6 +221,7 @@ AM_CONDITIONAL([WITH_CMDLINE],           [test "$with_cmdline"           = yes]) | |||
| AM_CONDITIONAL([WITH_ELF],               [test "$with_elf"               = yes]) | ||||
| AM_CONDITIONAL([WITH_FREE_LIST],         [test "$with_free_list"         = yes]) | ||||
| AM_CONDITIONAL([WITH_MBR],               [test "$with_mbr"               = yes]) | ||||
| AM_CONDITIONAL([WITH_MEMMAP],            [test "$with_memmap"            = yes]) | ||||
| AM_CONDITIONAL([WITH_MULTIBOOT2],        [test "$with_multiboot2"        = yes]) | ||||
| AM_CONDITIONAL([WITH_NTOA],              [test "$with_ntoa"              = yes]) | ||||
| AM_CONDITIONAL([WITH_PFA],               [test "$with_pfa"               = yes]) | ||||
|  | @ -265,6 +269,7 @@ AS_IF([test "$with_cmdline"           = yes], [AC_DEFINE([WITH_CMDLINE], | |||
| AS_IF([test "$with_elf"               = yes], [AC_DEFINE([WITH_ELF],               [1], [with ELF utils])]) | ||||
| AS_IF([test "$with_free_list"         = yes], [AC_DEFINE([WITH_FREE_LIST],         [1], [with free list memory allocator])]) | ||||
| AS_IF([test "$with_mbr"               = yes], [AC_DEFINE([WITH_MBR],               [1], [with MBR utils])]) | ||||
| AS_IF([test "$with_memmap"            = yes], [AC_DEFINE([WITH_MEMMAP],            [1], [with memory map])]) | ||||
| AS_IF([test "$with_multiboot2"        = yes], [AC_DEFINE([WITH_MULTIBOOT2],        [1], [with Multiboot 2 utils])]) | ||||
| AS_IF([test "$with_ntoa"              = yes], [AC_DEFINE([WITH_NTOA],              [1], [with ntoa])]) | ||||
| AS_IF([test "$with_pfa"               = yes], [AC_DEFINE([WITH_PFA],               [1], [with Page Frame Allocator])]) | ||||
|  | @ -293,6 +298,7 @@ AS_IF([test "$with_cmdline"      = no], [AC_SUBST([comment_line_cmdline],      [ | |||
| AS_IF([test "$with_elf"          = no], [AC_SUBST([comment_line_elf],          [//])]) | ||||
| AS_IF([test "$with_free_list"    = no], [AC_SUBST([comment_line_free_list],    [//])]) | ||||
| AS_IF([test "$with_mbr"          = no], [AC_SUBST([comment_line_mbr],          [//])]) | ||||
| AS_IF([test "$with_memmap"       = no], [AC_SUBST([comment_line_memmap],       [//])]) | ||||
| AS_IF([test "$with_multiboot2"   = no], [AC_SUBST([comment_line_multiboot2],   [//])]) | ||||
| AS_IF([test "$with_ntoa"         = no], [AC_SUBST([comment_line_ntoa],         [//])]) | ||||
| AS_IF([test "$with_pfa"          = no], [AC_SUBST([comment_line_pfa],          [//])]) | ||||
|  |  | |||
							
								
								
									
										1
									
								
								examples/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								examples/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -7,6 +7,7 @@ | |||
| /macro_container_of | ||||
| /macro_packing | ||||
| /macro_static_test | ||||
| /memmap | ||||
| /multiboot2_header_macro | ||||
| /ntoa | ||||
| /pfa | ||||
|  |  | |||
|  | @ -79,6 +79,16 @@ TESTS += macro_static_test | |||
| macro_static_test_LDADD = $(top_builddir)/libkernaux.la | ||||
| macro_static_test_SOURCES = main.c macro_static_test.c | ||||
| 
 | ||||
| ########## | ||||
| # memmap # | ||||
| ########## | ||||
| 
 | ||||
| if WITH_MEMMAP | ||||
| TESTS += memmap | ||||
| memmap_LDADD = $(top_builddir)/libkernaux.la | ||||
| memmap_SOURCES = main.c memmap.c | ||||
| endif | ||||
| 
 | ||||
| ########################### | ||||
| # multiboot2_header_macro # | ||||
| ########################### | ||||
|  |  | |||
							
								
								
									
										59
									
								
								examples/memmap.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								examples/memmap.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| #define KERNAUX_ACCESS_PROTECTED | ||||
| 
 | ||||
| #include <kernaux/free_list.h> | ||||
| #include <kernaux/generic/display.h> | ||||
| #include <kernaux/macro.h> | ||||
| #include <kernaux/memmap.h> | ||||
| 
 | ||||
| #include <assert.h> | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| static char malloc_memory[8192]; | ||||
| 
 | ||||
| static void my_putc(void *const display KERNAUX_UNUSED, const char c) | ||||
| { | ||||
|     putchar(c); | ||||
| } | ||||
| 
 | ||||
| static void my_vprintf( | ||||
|     void *const display KERNAUX_UNUSED, | ||||
|     const char *const format, | ||||
|     va_list va | ||||
| ) { | ||||
|     vprintf(format, va); | ||||
| } | ||||
| 
 | ||||
| static const struct KernAux_Display display = { | ||||
|     .putc = my_putc, | ||||
|     .vprintf = my_vprintf, | ||||
| }; | ||||
| 
 | ||||
| void example_main() | ||||
| { | ||||
|     struct KernAux_FreeList malloc = KernAux_FreeList_create(NULL); | ||||
|     KernAux_FreeList_add_zone(&malloc, malloc_memory, sizeof(malloc_memory)); | ||||
| 
 | ||||
|     KernAux_Memmap_Builder memmap_builder = | ||||
|         KernAux_Memmap_Builder_new(&malloc.malloc); | ||||
|     assert(memmap_builder); | ||||
| 
 | ||||
|     assert(KernAux_Memmap_Builder_add(memmap_builder, 0x0,        654336,    true,  "available")); | ||||
|     assert(KernAux_Memmap_Builder_add(memmap_builder, 0x9fc00,    1024,      false, "reserved")); | ||||
|     assert(KernAux_Memmap_Builder_add(memmap_builder, 0xf0000,    65536,     false, "reserved")); | ||||
|     assert(KernAux_Memmap_Builder_add(memmap_builder, 0x100000,   133038080, true,  "available")); | ||||
|     assert(KernAux_Memmap_Builder_add(memmap_builder, 0x7fe0000,  131072,    false, "reserved")); | ||||
|     assert(KernAux_Memmap_Builder_add(memmap_builder, 0xfffc0000, 262144,    false, "reserved")); | ||||
| 
 | ||||
|     assert(KernAux_Memmap_Builder_add(memmap_builder, 0x400000,   8192,      false, "kernel code")); | ||||
|     assert(KernAux_Memmap_Builder_add(memmap_builder, 0x402000,   4096,      false, "kernel data")); | ||||
| 
 | ||||
|     KernAux_Memmap memmap = | ||||
|         KernAux_Memmap_Builder_finish_and_free(memmap_builder); | ||||
|     assert(memmap); | ||||
| 
 | ||||
|     KernAux_Memmap_print(memmap, &display); | ||||
| 
 | ||||
|     KERNAUX_MEMMAP_FREE(memmap); | ||||
| } | ||||
|  | @ -19,6 +19,7 @@ nobase_include_HEADERS = \ | |||
| 	kernaux/macro/packing_end.run        \ | ||||
| 	kernaux/macro/packing_start.run      \ | ||||
| 	kernaux/mbr.h                        \ | ||||
| 	kernaux/memmap.h                     \ | ||||
| 	kernaux/multiboot2.h                 \ | ||||
| 	kernaux/multiboot2/header_enums.h    \ | ||||
| 	kernaux/multiboot2/header_helpers.h  \ | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include <kernaux/generic/mutex.h> | ||||
| #include <kernaux/macro.h> | ||||
| #include <kernaux/mbr.h> | ||||
| #include <kernaux/memmap.h> | ||||
| #include <kernaux/multiboot2.h> | ||||
| #include <kernaux/ntoa.h> | ||||
| #include <kernaux/pfa.h> | ||||
|  |  | |||
							
								
								
									
										73
									
								
								include/kernaux/memmap.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								include/kernaux/memmap.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,73 @@ | |||
| #ifndef KERNAUX_INCLUDED_MEMMAP | ||||
| #define KERNAUX_INCLUDED_MEMMAP | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #include <kernaux/generic/display.h> | ||||
| #include <kernaux/generic/malloc.h> | ||||
| #include <kernaux/macro.h> | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #define KERNAUX_MEMMAP_FREE(memmap) do { \ | ||||
|     KernAux_Memmap_free(memmap); \ | ||||
|     memmap = NULL; \ | ||||
| } while (0) | ||||
| 
 | ||||
| /*********
 | ||||
|  * Types * | ||||
|  *********/ | ||||
| 
 | ||||
| typedef const struct KernAux_Memmap_Node { | ||||
|     const struct KernAux_Memmap_Node *parent_node; | ||||
|     unsigned char level; | ||||
|     uint64_t mem_start, mem_end, mem_size; | ||||
|     bool is_available; | ||||
|     const char *tag; | ||||
|     const struct KernAux_Memmap_Node *next, *children; | ||||
| } *KernAux_Memmap_Node; | ||||
| 
 | ||||
| typedef const struct KernAux_Memmap { | ||||
|     KernAux_Memmap_Node root_node; | ||||
| 
 | ||||
|     KernAux_Malloc KERNAUX_PRIVATE_FIELD(malloc); | ||||
| } *KernAux_Memmap; | ||||
| 
 | ||||
| typedef struct KernAux_Memmap_Builder { | ||||
|     KernAux_Memmap KERNAUX_PRIVATE_FIELD(memmap); | ||||
| } *KernAux_Memmap_Builder; | ||||
| 
 | ||||
| /*************
 | ||||
|  * Functions * | ||||
|  *************/ | ||||
| 
 | ||||
| KernAux_Memmap_Builder | ||||
| KernAux_Memmap_Builder_new(KernAux_Malloc malloc); | ||||
| 
 | ||||
| KernAux_Memmap_Node | ||||
| KernAux_Memmap_Builder_add( | ||||
|     KernAux_Memmap_Builder builder, | ||||
|     uint64_t mem_start, | ||||
|     uint64_t mem_size, | ||||
|     bool is_available, | ||||
|     const char *tag | ||||
| ); | ||||
| 
 | ||||
| KernAux_Memmap | ||||
| KernAux_Memmap_Builder_finish_and_free(KernAux_Memmap_Builder builder); | ||||
| 
 | ||||
| void KernAux_Memmap_free(KernAux_Memmap memmap); | ||||
| void KernAux_Memmap_print(KernAux_Memmap memmap, KernAux_Display display); | ||||
| 
 | ||||
| KernAux_Memmap_Node | ||||
| KernAux_Memmap_node_by_addr(KernAux_Memmap memmap, uint64_t addr); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
|  | @ -8,6 +8,7 @@ extern "C" { | |||
| #include <kernaux/generic/display.h> | ||||
| #include <kernaux/generic/malloc.h> | ||||
| #include <kernaux/macro.h> | ||||
| #include <kernaux/memmap.h> | ||||
| #include <kernaux/multiboot2/header_macro.h> | ||||
| 
 | ||||
| #include <stdint.h> | ||||
|  | @ -560,6 +561,15 @@ KERNAUX_STATIC_TEST_STRUCT_SIZE( | |||
| #include <kernaux/multiboot2/header_print.h> | ||||
| #include <kernaux/multiboot2/info_print.h> | ||||
| 
 | ||||
| /*******************
 | ||||
|  * Other functions * | ||||
|  *******************/ | ||||
| 
 | ||||
| bool KernAux_Multiboot2_Info_build_memmap_from_memmap( | ||||
|     const struct KernAux_Multiboot2_Info *multiboot2_info, | ||||
|     KernAux_Memmap_Builder builder | ||||
| ); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| @comment_line_elf@#define KERNAUX_VERSION_WITH_ELF | ||||
| @comment_line_free_list@#define KERNAUX_VERSION_WITH_FREE_LIST | ||||
| @comment_line_mbr@#define KERNAUX_VERSION_WITH_MBR | ||||
| @comment_line_memmap@#define KERNAUX_VERSION_WITH_MEMMAP | ||||
| @comment_line_multiboot2@#define KERNAUX_VERSION_WITH_MULTIBOOT2 | ||||
| @comment_line_ntoa@#define KERNAUX_VERSION_WITH_NTOA | ||||
| @comment_line_pfa@#define KERNAUX_VERSION_WITH_PFA | ||||
|  |  | |||
							
								
								
									
										303
									
								
								src/memmap.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								src/memmap.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,303 @@ | |||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
| 
 | ||||
| #include "assert.h" | ||||
| 
 | ||||
| #include <kernaux/generic/display.h> | ||||
| #include <kernaux/generic/malloc.h> | ||||
| #include <kernaux/macro.h> | ||||
| #include <kernaux/memmap.h> | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| static void free_node(KernAux_Malloc malloc, struct KernAux_Memmap_Node *node); | ||||
| static KernAux_Memmap_Node node_by_addr( | ||||
|     KernAux_Memmap_Node parent_node, | ||||
|     uint64_t addr | ||||
| ); | ||||
| static void print_nodes( | ||||
|     KernAux_Memmap_Node node, | ||||
|     KernAux_Display display, | ||||
|     unsigned indentation | ||||
| ); | ||||
| 
 | ||||
| KernAux_Memmap_Builder | ||||
| KernAux_Memmap_Builder_new(const KernAux_Malloc malloc) | ||||
| { | ||||
|     KERNAUX_NOTNULL(malloc); | ||||
| 
 | ||||
|     struct KernAux_Memmap_Builder *const builder = | ||||
|         KernAux_Malloc_malloc(malloc, sizeof(*builder)); | ||||
|     if (!builder) { | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     struct KernAux_Memmap *const memmap = | ||||
|         KernAux_Malloc_malloc(malloc, sizeof(*memmap)); | ||||
|     if (!memmap) { | ||||
|         KernAux_Malloc_free(malloc, builder); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     struct KernAux_Memmap_Node *const root_node = | ||||
|         KernAux_Malloc_malloc(malloc, sizeof(*root_node)); | ||||
|     if (!root_node) { | ||||
|         KernAux_Malloc_free(malloc, memmap); | ||||
|         KernAux_Malloc_free(malloc, builder); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     *root_node = (struct KernAux_Memmap_Node){ | ||||
|         .parent_node = NULL, | ||||
|         .level = 0, | ||||
|         .mem_start = 0x0, | ||||
|         .mem_end   = 0xffffffffffffffff, // 2**64 - 1
 | ||||
|         .mem_size  = 0xffffffffffffffff, // 2**64 - 1
 | ||||
|         .is_available = false, | ||||
|         .tag = NULL, | ||||
|         .next = NULL, | ||||
|         .children = NULL, | ||||
|     }; | ||||
|     *memmap = (struct KernAux_Memmap){ | ||||
|         .malloc = malloc, | ||||
|         .root_node = root_node, | ||||
|     }; | ||||
|     *builder = (struct KernAux_Memmap_Builder){ | ||||
|         .memmap = memmap, | ||||
|     }; | ||||
| 
 | ||||
|     return builder; | ||||
| } | ||||
| 
 | ||||
| KernAux_Memmap_Node KernAux_Memmap_Builder_add( | ||||
|     const KernAux_Memmap_Builder builder, | ||||
|     const uint64_t mem_start, | ||||
|     const uint64_t mem_size, | ||||
|     const bool is_available, | ||||
|     const char *tag | ||||
| ) { | ||||
|     KERNAUX_NOTNULL(builder); | ||||
|     KERNAUX_ASSERT(builder->memmap); | ||||
|     KERNAUX_ASSERT(builder->memmap->root_node); | ||||
|     KERNAUX_ASSERT(builder->memmap->malloc); | ||||
| 
 | ||||
|     if (mem_size == 0) goto fail; | ||||
| 
 | ||||
|     char *tag_copy = NULL; | ||||
|     if (tag) { | ||||
|         tag_copy = | ||||
|             KernAux_Malloc_malloc(builder->memmap->malloc, strlen(tag) + 1); | ||||
|         if (!tag_copy) goto fail; | ||||
|         strcpy(tag_copy, tag); | ||||
|     } | ||||
| 
 | ||||
|     struct KernAux_Memmap_Node *const new_node = | ||||
|         KernAux_Malloc_malloc(builder->memmap->malloc, sizeof(*new_node)); | ||||
|     if (!new_node) goto fail_after_tag; | ||||
| 
 | ||||
|     new_node->mem_start = mem_start; | ||||
|     new_node->mem_size = mem_size; | ||||
|     new_node->mem_end = mem_start + mem_size - 1; | ||||
|     new_node->is_available = is_available; | ||||
|     new_node->tag = tag_copy; | ||||
| 
 | ||||
|     new_node->parent_node = | ||||
|         KernAux_Memmap_node_by_addr(builder->memmap, new_node->mem_start); | ||||
|     KERNAUX_ASSERT(new_node->parent_node); | ||||
| 
 | ||||
|     if (new_node->mem_start < new_node->parent_node->mem_start || | ||||
|         new_node->mem_end > new_node->parent_node->mem_end) | ||||
|     { | ||||
|         goto fail_after_new_node; | ||||
|     } | ||||
| 
 | ||||
|     new_node->level = new_node->parent_node->level + 1; | ||||
|     KERNAUX_ASSERT(new_node->level > 0); | ||||
| 
 | ||||
|     if (new_node->parent_node->children) { | ||||
|         for ( | ||||
|             struct KernAux_Memmap_Node *curr_node = | ||||
|                 (struct KernAux_Memmap_Node*)new_node->parent_node->children; | ||||
|             curr_node; | ||||
|             curr_node = (struct KernAux_Memmap_Node*)curr_node->next | ||||
|         ) { | ||||
|             if (!curr_node->next || | ||||
|                 curr_node->next->mem_start > new_node->mem_start) | ||||
|             { | ||||
|                 if (new_node->next && | ||||
|                     new_node->mem_end >= new_node->next->mem_start) | ||||
|                 { | ||||
|                     goto fail_after_new_node; | ||||
|                 } | ||||
|                 new_node->next = curr_node->next; | ||||
|                 curr_node->next = new_node; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         new_node->next = NULL; | ||||
|         ((struct KernAux_Memmap_Node*)new_node->parent_node)->children = | ||||
|             new_node; | ||||
|     } | ||||
| 
 | ||||
|     return new_node; | ||||
| 
 | ||||
| fail_after_new_node: | ||||
|     KernAux_Malloc_free(builder->memmap->malloc, new_node); | ||||
| fail_after_tag: | ||||
|     if (tag_copy) KernAux_Malloc_free(builder->memmap->malloc, tag_copy); | ||||
| fail: | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| KernAux_Memmap | ||||
| KernAux_Memmap_Builder_finish_and_free(const KernAux_Memmap_Builder builder) | ||||
| { | ||||
|     KERNAUX_NOTNULL(builder); | ||||
|     KERNAUX_ASSERT(builder->memmap); | ||||
|     KERNAUX_ASSERT(builder->memmap->root_node); | ||||
|     KERNAUX_ASSERT(builder->memmap->malloc); | ||||
| 
 | ||||
|     KernAux_Memmap memmap = builder->memmap; | ||||
|     builder->memmap = NULL; | ||||
|     KernAux_Malloc_free(memmap->malloc, builder); | ||||
|     return memmap; | ||||
| } | ||||
| 
 | ||||
| void KernAux_Memmap_free(const KernAux_Memmap memmap) | ||||
| { | ||||
|     KERNAUX_NOTNULL(memmap); | ||||
|     KERNAUX_ASSERT(memmap->root_node); | ||||
|     KERNAUX_ASSERT(memmap->malloc); | ||||
|     KERNAUX_ASSERT(memmap->root_node->next == NULL); | ||||
| 
 | ||||
|     free_node(memmap->malloc, (struct KernAux_Memmap_Node*)memmap->root_node); | ||||
| 
 | ||||
|     KernAux_Malloc malloc = memmap->malloc; | ||||
| 
 | ||||
|     ((struct KernAux_Memmap*)memmap)->root_node = NULL; | ||||
|     ((struct KernAux_Memmap*)memmap)->malloc = NULL; | ||||
| 
 | ||||
|     KernAux_Malloc_free(malloc, (void*)memmap); | ||||
| } | ||||
| 
 | ||||
| void KernAux_Memmap_print( | ||||
|     const KernAux_Memmap memmap, | ||||
|     const KernAux_Display display | ||||
| ) { | ||||
|     KERNAUX_NOTNULL(memmap); | ||||
|     KERNAUX_ASSERT(memmap->root_node); | ||||
|     KERNAUX_ASSERT(memmap->malloc); | ||||
|     KERNAUX_ASSERT(memmap->root_node->next == NULL); | ||||
| 
 | ||||
|     print_nodes(memmap->root_node, display, 0); | ||||
| } | ||||
| 
 | ||||
| KernAux_Memmap_Node | ||||
| KernAux_Memmap_node_by_addr(const KernAux_Memmap memmap, const uint64_t addr) | ||||
| { | ||||
|     return node_by_addr(memmap->root_node, addr); | ||||
| } | ||||
| 
 | ||||
| void free_node( | ||||
|     const KernAux_Malloc malloc, | ||||
|     struct KernAux_Memmap_Node *const node | ||||
| ) { | ||||
|     KERNAUX_NOTNULL(malloc); | ||||
|     KERNAUX_NOTNULL(node); | ||||
| 
 | ||||
|     for ( | ||||
|         struct KernAux_Memmap_Node *child_node = | ||||
|             (struct KernAux_Memmap_Node*)node->children; | ||||
|         child_node; | ||||
|         child_node = (struct KernAux_Memmap_Node*)child_node->next | ||||
|     ) { | ||||
|         free_node(malloc, child_node); | ||||
|     } | ||||
| 
 | ||||
|     if (node->tag) KernAux_Malloc_free(malloc, (void*)node->tag); | ||||
|     KernAux_Malloc_free(malloc, node); | ||||
| } | ||||
| 
 | ||||
| KernAux_Memmap_Node node_by_addr( | ||||
|     const KernAux_Memmap_Node parent_node, | ||||
|     const uint64_t addr | ||||
| ) { | ||||
|     KERNAUX_NOTNULL(parent_node); | ||||
| 
 | ||||
|     if (parent_node->mem_start > addr || parent_node->mem_end < addr) { | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     for ( | ||||
|         KernAux_Memmap_Node child_node = parent_node->children; | ||||
|         child_node; | ||||
|         child_node = child_node->next | ||||
|     ) { | ||||
|         const KernAux_Memmap_Node node = node_by_addr(child_node, addr); | ||||
|         if (node) return node; | ||||
|     } | ||||
| 
 | ||||
|     return parent_node; | ||||
| } | ||||
| 
 | ||||
| #define PRINT(s)   do { KernAux_Display_print  (display, s); } while (0) | ||||
| #define PRINTLN(s) do { KernAux_Display_println(display, s); } while (0) | ||||
| 
 | ||||
| #define PRINTLNF(format, ...) \ | ||||
|     do { KernAux_Display_printlnf(display, format, __VA_ARGS__); } while (0) | ||||
| 
 | ||||
| #define INDENT do { \ | ||||
|     for (unsigned index = 0; index < indentation; ++index) PRINT("  "); \ | ||||
| } while (0) | ||||
| 
 | ||||
| void print_nodes( | ||||
|     KernAux_Memmap_Node node, | ||||
|     const KernAux_Display display, | ||||
|     const unsigned indentation | ||||
| ) { | ||||
|     for (; node; node = node->next) { | ||||
|         INDENT; | ||||
|         PRINTLN("{"); | ||||
| 
 | ||||
|         KERNAUX_CAST_CONST(unsigned long long, mem_start, node->mem_start); | ||||
|         KERNAUX_CAST_CONST(unsigned long long, mem_size,  node->mem_size); | ||||
|         KERNAUX_CAST_CONST(unsigned long long, mem_end,   node->mem_end); | ||||
|         const bool is_available = node->is_available; | ||||
| 
 | ||||
|         INDENT; | ||||
|         PRINTLNF("  unsigned char level: %hhu", node->level); | ||||
|         INDENT; | ||||
|         PRINTLNF("  u64 mem_start: 0x%llx", mem_start); | ||||
|         INDENT; | ||||
|         PRINTLNF("  u64 mem_size:  %llu",   mem_size); | ||||
|         INDENT; | ||||
|         PRINTLNF("  u64 mem_end:   0x%llx", mem_end); | ||||
|         INDENT; | ||||
|         PRINTLNF("  bool is_available: %s", is_available ? "TRUE" : "FALSE"); | ||||
|         INDENT; | ||||
|         if (node->tag) { | ||||
|             PRINTLNF("  char* tag: \"%s\"", node->tag); | ||||
|         } else { | ||||
|             PRINTLN("  char* tag: NULL"); | ||||
|         } | ||||
| 
 | ||||
|         if (node->children) { | ||||
|             INDENT; | ||||
|             PRINTLN("  struct* children: ["); | ||||
|             print_nodes(node->children, display, indentation + 2); | ||||
|             INDENT; | ||||
|             PRINTLN("  ]"); | ||||
|         } else { | ||||
|             INDENT; | ||||
|             PRINTLN("  struct* children: []"); | ||||
|         } | ||||
| 
 | ||||
|         INDENT; | ||||
|         PRINTLN("}"); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										67
									
								
								src/multiboot2/info_convert.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/multiboot2/info_convert.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,67 @@ | |||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
| 
 | ||||
| #include "../assert.h" | ||||
| 
 | ||||
| #include <kernaux/generic/malloc.h> | ||||
| #include <kernaux/macro.h> | ||||
| #include <kernaux/memmap.h> | ||||
| #include <kernaux/multiboot2.h> | ||||
| 
 | ||||
| #include <stddef.h> | ||||
| 
 | ||||
| #ifdef WITH_MEMMAP | ||||
| bool KernAux_Multiboot2_Info_build_memmap_from_memmap( | ||||
|     const struct KernAux_Multiboot2_Info *const multiboot2_info, | ||||
|     const KernAux_Memmap_Builder builder | ||||
| ) { | ||||
|     KERNAUX_NOTNULL(multiboot2_info); | ||||
|     KERNAUX_NOTNULL(builder); | ||||
| 
 | ||||
|     if (!KernAux_Multiboot2_Info_is_valid(multiboot2_info)) return false; | ||||
| 
 | ||||
|     const struct KernAux_Multiboot2_ITag_MemoryMap *const memory_map_tag = | ||||
|         (const struct KernAux_Multiboot2_ITag_MemoryMap*) | ||||
|         KernAux_Multiboot2_Info_first_tag_with_type( | ||||
|             multiboot2_info, | ||||
|             KERNAUX_MULTIBOOT2_ITAG_MEMORY_MAP | ||||
|         ); | ||||
|     if (!memory_map_tag) return false; | ||||
| 
 | ||||
|     const void *const data = KERNAUX_MULTIBOOT2_DATA(memory_map_tag); | ||||
|     size_t data_size = memory_map_tag->base.size - sizeof(*memory_map_tag); | ||||
|     const void *const data_end = ((const char*)data) + data_size; | ||||
| 
 | ||||
|     if (memory_map_tag->entry_size < | ||||
|         sizeof(struct KernAux_Multiboot2_ITag_MemoryMap_EntryBase)) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     for ( | ||||
|         const struct KernAux_Multiboot2_ITag_MemoryMap_EntryBase *entry = data; | ||||
|         (const char*)entry < (const char*)data_end; | ||||
|         entry = | ||||
|             (const struct KernAux_Multiboot2_ITag_MemoryMap_EntryBase*) | ||||
|             (((const char*)entry) + memory_map_tag->entry_size) | ||||
|     ) { | ||||
|         const void *const node = KernAux_Memmap_Builder_add( | ||||
|             builder, | ||||
|             entry->base_addr, | ||||
|             entry->length, | ||||
|             entry->type == KERNAUX_MULTIBOOT2_MEMMAP_AVAILABLE, | ||||
|             KernAux_Multiboot2_ITag_MemoryMap_EntryBase_Type_to_str( | ||||
|                 entry->type | ||||
|             ) | ||||
|         ); | ||||
| 
 | ||||
|         if (!node) { | ||||
|             KernAux_Memmap_Builder_finish_and_free(builder); | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										2
									
								
								tests/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								tests/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -11,11 +11,13 @@ | |||
| /test_elf | ||||
| /test_free_list | ||||
| /test_mbr | ||||
| /test_memmap | ||||
| /test_multiboot2_common_packing | ||||
| /test_multiboot2_header_helpers | ||||
| /test_multiboot2_header_print | ||||
| /test_multiboot2_header_print.c | ||||
| /test_multiboot2_header_validation | ||||
| /test_multiboot2_info_convert_memmap | ||||
| /test_multiboot2_info_helpers | ||||
| /test_multiboot2_info_print | ||||
| /test_multiboot2_info_print.c | ||||
|  |  | |||
|  | @ -168,6 +168,18 @@ test_mbr_SOURCES = \ | |||
| 	test_mbr.c | ||||
| endif | ||||
| 
 | ||||
| ############### | ||||
| # test_memmap # | ||||
| ############### | ||||
| 
 | ||||
| if WITH_MEMMAP | ||||
| TESTS += test_memmap | ||||
| test_memmap_LDADD = $(top_builddir)/libkernaux.la | ||||
| test_memmap_SOURCES = \ | ||||
| 	main.c \ | ||||
| 	test_memmap.c | ||||
| endif | ||||
| 
 | ||||
| ################################## | ||||
| # test_multiboot2_common_packing # | ||||
| ################################## | ||||
|  | @ -229,6 +241,22 @@ test_multiboot2_header_validation_SOURCES = \ | |||
| 	../fixtures/multiboot2_header_example2.h | ||||
| endif | ||||
| 
 | ||||
| ####################################### | ||||
| # test_multiboot2_info_convert_memmap # | ||||
| ####################################### | ||||
| 
 | ||||
| if WITH_MULTIBOOT2 | ||||
| if WITH_MEMMAP | ||||
| TESTS += test_multiboot2_info_convert_memmap | ||||
| test_multiboot2_info_convert_memmap_LDADD = $(top_builddir)/libkernaux.la | ||||
| test_multiboot2_info_convert_memmap_SOURCES = \ | ||||
| 	main.c \ | ||||
| 	test_multiboot2_info_convert_memmap.c \ | ||||
| 	../fixtures/multiboot2_header_example2.h \ | ||||
| 	../fixtures/multiboot2_info_example2.h | ||||
| endif | ||||
| endif | ||||
| 
 | ||||
| ################################ | ||||
| # test_multiboot2_info_helpers # | ||||
| ################################ | ||||
|  |  | |||
							
								
								
									
										145
									
								
								tests/test_memmap.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								tests/test_memmap.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,145 @@ | |||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
| 
 | ||||
| #include <kernaux/free_list.h> | ||||
| #include <kernaux/memmap.h> | ||||
| 
 | ||||
| #include <assert.h> | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| static char buffer[4096]; | ||||
| static struct KernAux_FreeList malloc; | ||||
| 
 | ||||
| void test_main() | ||||
| { | ||||
|     malloc = KernAux_FreeList_create(NULL); | ||||
|     KernAux_FreeList_add_zone(&malloc, buffer, sizeof(buffer)); | ||||
| 
 | ||||
|     KernAux_Memmap_Builder memmap_builder = | ||||
|         KernAux_Memmap_Builder_new(&malloc.malloc); | ||||
|     assert(memmap_builder); | ||||
| 
 | ||||
|     // Level 1
 | ||||
|     KernAux_Memmap_Node foo_node = | ||||
|         KernAux_Memmap_Builder_add(memmap_builder, 0x0ULL,                0x8000000000000000ULL, true,  "foo"); | ||||
|     KernAux_Memmap_Node bar_node = | ||||
|         KernAux_Memmap_Builder_add(memmap_builder, 0x8000000000000000ULL, 0x8000000000000000ULL, false, "bar"); | ||||
| 
 | ||||
|     // Level 2
 | ||||
|     KernAux_Memmap_Node foo1_node = | ||||
|         KernAux_Memmap_Builder_add(memmap_builder, 0x0ULL,                0x4000000000000000ULL, true,  "foo1"); | ||||
|     KernAux_Memmap_Node foo2_node = | ||||
|         KernAux_Memmap_Builder_add(memmap_builder, 0x4000000000000000ULL, 0x4000000000000000ULL, false, "foo2"); | ||||
|     KernAux_Memmap_Node bar1_node = | ||||
|         KernAux_Memmap_Builder_add(memmap_builder, 0x8000000000000000ULL, 0x4000000000000000ULL, true,  "bar1"); | ||||
|     KernAux_Memmap_Node bar2_node = | ||||
|         KernAux_Memmap_Builder_add(memmap_builder, 0xc000000000000000ULL, 0x4000000000000000ULL, false, "bar2"); | ||||
| 
 | ||||
|     // Level 1
 | ||||
|     assert(foo_node); | ||||
|     assert(bar_node); | ||||
| 
 | ||||
|     // Level 2
 | ||||
|     assert(foo1_node); | ||||
|     assert(foo2_node); | ||||
|     assert(bar1_node); | ||||
|     assert(bar2_node); | ||||
| 
 | ||||
|     const KernAux_Memmap memmap = | ||||
|         KernAux_Memmap_Builder_finish_and_free(memmap_builder); | ||||
|     assert(memmap); | ||||
| 
 | ||||
|     assert(memmap->root_node->next == NULL); | ||||
|     assert(memmap->root_node->children == foo_node); | ||||
| 
 | ||||
|     assert(foo_node->next == bar_node); | ||||
|     assert(bar_node->next == NULL); | ||||
| 
 | ||||
|     assert(foo_node->children == foo1_node); | ||||
|     assert(foo1_node->next == foo2_node); | ||||
|     assert(foo1_node->children == NULL); | ||||
|     assert(foo2_node->next == NULL); | ||||
|     assert(foo2_node->children == NULL); | ||||
| 
 | ||||
|     assert(bar_node->children == bar1_node); | ||||
|     assert(bar1_node->next == bar2_node); | ||||
|     assert(bar1_node->children == NULL); | ||||
|     assert(bar2_node->next == NULL); | ||||
|     assert(bar2_node->children == NULL); | ||||
| 
 | ||||
|     assert(foo1_node == KernAux_Memmap_node_by_addr(memmap, 0x0ULL)); | ||||
|     assert(foo1_node == KernAux_Memmap_node_by_addr(memmap, 0x0ULL + 0x4000000000000000ULL / 2)); | ||||
|     assert(foo1_node == KernAux_Memmap_node_by_addr(memmap, 0x0ULL + 0x4000000000000000ULL - 1)); | ||||
| 
 | ||||
|     assert(foo2_node == KernAux_Memmap_node_by_addr(memmap, 0x4000000000000000ULL)); | ||||
|     assert(foo2_node == KernAux_Memmap_node_by_addr(memmap, 0x4000000000000000ULL + 0x4000000000000000ULL / 2)); | ||||
|     assert(foo2_node == KernAux_Memmap_node_by_addr(memmap, 0x4000000000000000ULL + 0x4000000000000000ULL - 1)); | ||||
| 
 | ||||
|     assert(bar1_node == KernAux_Memmap_node_by_addr(memmap, 0x8000000000000000ULL)); | ||||
|     assert(bar1_node == KernAux_Memmap_node_by_addr(memmap, 0x8000000000000000ULL + 0x4000000000000000ULL / 2)); | ||||
|     assert(bar1_node == KernAux_Memmap_node_by_addr(memmap, 0x8000000000000000ULL + 0x4000000000000000ULL - 1)); | ||||
| 
 | ||||
|     assert(bar2_node == KernAux_Memmap_node_by_addr(memmap, 0xc000000000000000ULL)); | ||||
|     assert(bar2_node == KernAux_Memmap_node_by_addr(memmap, 0xc000000000000000ULL + 0x4000000000000000ULL / 2)); | ||||
|     assert(bar2_node == KernAux_Memmap_node_by_addr(memmap, 0xc000000000000000ULL + 0x4000000000000000ULL - 1)); | ||||
| 
 | ||||
|     // Level 0
 | ||||
| 
 | ||||
|     assert(memmap->root_node->parent_node == NULL); | ||||
|     assert(memmap->root_node->level == 0); | ||||
| 
 | ||||
|     // Level 1
 | ||||
| 
 | ||||
|     assert(foo_node->parent_node == memmap->root_node); | ||||
|     assert(foo_node->level == 1); | ||||
|     assert(foo_node->mem_start == 0x0); | ||||
|     assert(foo_node->mem_size  == 0x8000000000000000ULL); | ||||
|     assert(foo_node->mem_end   == 0x7fffffffffffffffULL); | ||||
|     assert(foo_node->is_available == true); | ||||
|     assert(strcmp(foo_node->tag, "foo") == 0); | ||||
| 
 | ||||
|     assert(bar_node->parent_node == memmap->root_node); | ||||
|     assert(bar_node->level == 1); | ||||
|     assert(bar_node->mem_start == 0x8000000000000000ULL); | ||||
|     assert(bar_node->mem_size  == 0x8000000000000000ULL); | ||||
|     assert(bar_node->mem_end   == 0xffffffffffffffffULL); | ||||
|     assert(bar_node->is_available == false); | ||||
|     assert(strcmp(bar_node->tag, "bar") == 0); | ||||
| 
 | ||||
|     // Level 2
 | ||||
| 
 | ||||
|     assert(foo1_node->parent_node == foo_node); | ||||
|     assert(foo1_node->level == 2); | ||||
|     assert(foo1_node->mem_start == 0x0); | ||||
|     assert(foo1_node->mem_size  == 0x4000000000000000ULL); | ||||
|     assert(foo1_node->mem_end   == 0x3fffffffffffffffULL); | ||||
|     assert(foo1_node->is_available == true); | ||||
|     assert(strcmp(foo1_node->tag, "foo1") == 0); | ||||
| 
 | ||||
|     assert(foo2_node->parent_node == foo_node); | ||||
|     assert(foo2_node->level == 2); | ||||
|     assert(foo2_node->mem_start == 0x4000000000000000ULL); | ||||
|     assert(foo2_node->mem_size  == 0x4000000000000000ULL); | ||||
|     assert(foo2_node->mem_end   == 0x7fffffffffffffffULL); | ||||
|     assert(foo2_node->is_available == false); | ||||
|     assert(strcmp(foo2_node->tag, "foo2") == 0); | ||||
| 
 | ||||
|     assert(bar1_node->parent_node == bar_node); | ||||
|     assert(bar1_node->level == 2); | ||||
|     assert(bar1_node->mem_start == 0x8000000000000000ULL); | ||||
|     assert(bar1_node->mem_size  == 0x4000000000000000ULL); | ||||
|     assert(bar1_node->mem_end   == 0xbfffffffffffffffULL); | ||||
|     assert(bar1_node->is_available == true); | ||||
|     assert(strcmp(bar1_node->tag, "bar1") == 0); | ||||
| 
 | ||||
|     assert(bar2_node->parent_node == bar_node); | ||||
|     assert(bar2_node->level == 2); | ||||
|     assert(bar2_node->mem_start == 0xc000000000000000ULL); | ||||
|     assert(bar2_node->mem_size  == 0x4000000000000000ULL); | ||||
|     assert(bar2_node->mem_end   == 0xffffffffffffffffULL); | ||||
|     assert(bar2_node->is_available == false); | ||||
|     assert(strcmp(bar2_node->tag, "bar2") == 0); | ||||
| } | ||||
							
								
								
									
										154
									
								
								tests/test_multiboot2_info_convert_memmap.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								tests/test_multiboot2_info_convert_memmap.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,154 @@ | |||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
| 
 | ||||
| #include <kernaux/free_list.h> | ||||
| #include <kernaux/memmap.h> | ||||
| #include <kernaux/multiboot2.h> | ||||
| 
 | ||||
| #include <assert.h> | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "../fixtures/multiboot2_info_example0.h" | ||||
| #include "../fixtures/multiboot2_info_example1.h" | ||||
| #include "../fixtures/multiboot2_info_example2.h" | ||||
| 
 | ||||
| static char buffer[4096]; | ||||
| 
 | ||||
| static void test_examples_1_and_2(KernAux_Memmap memmap); | ||||
| 
 | ||||
| void test_main() | ||||
| { | ||||
|     struct KernAux_FreeList malloc = KernAux_FreeList_create(NULL); | ||||
|     KernAux_FreeList_add_zone(&malloc, buffer, sizeof(buffer)); | ||||
| 
 | ||||
|     { | ||||
|         const KernAux_Memmap_Builder builder = | ||||
|             KernAux_Memmap_Builder_new(&malloc.malloc); | ||||
|         assert(builder != NULL); | ||||
| 
 | ||||
|         const bool result = KernAux_Multiboot2_Info_build_memmap_from_memmap( | ||||
|             &multiboot2_info_example0.multiboot2_info, | ||||
|             builder | ||||
|         ); | ||||
|         assert(!result); | ||||
|     } | ||||
| 
 | ||||
|     { | ||||
|         const KernAux_Memmap_Builder builder = | ||||
|             KernAux_Memmap_Builder_new(&malloc.malloc); | ||||
|         assert(builder != NULL); | ||||
| 
 | ||||
|         const bool result = KernAux_Multiboot2_Info_build_memmap_from_memmap( | ||||
|             (const struct KernAux_Multiboot2_Info*) | ||||
|                 &multiboot2_info_example1, | ||||
|             builder | ||||
|         ); | ||||
|         assert(result); | ||||
| 
 | ||||
|         const KernAux_Memmap memmap = | ||||
|             KernAux_Memmap_Builder_finish_and_free(builder); | ||||
|         assert(memmap); | ||||
| 
 | ||||
|         test_examples_1_and_2(memmap); | ||||
| 
 | ||||
|         KernAux_Memmap_free(memmap); | ||||
|     } | ||||
| 
 | ||||
|     { | ||||
|         const KernAux_Memmap_Builder builder = | ||||
|             KernAux_Memmap_Builder_new(&malloc.malloc); | ||||
|         assert(builder != NULL); | ||||
| 
 | ||||
|         const bool result = KernAux_Multiboot2_Info_build_memmap_from_memmap( | ||||
|             &multiboot2_info_example2.multiboot2_info, | ||||
|             builder | ||||
|         ); | ||||
|         assert(result); | ||||
| 
 | ||||
|         const KernAux_Memmap memmap = | ||||
|             KernAux_Memmap_Builder_finish_and_free(builder); | ||||
|         assert(memmap); | ||||
| 
 | ||||
|         test_examples_1_and_2(memmap); | ||||
| 
 | ||||
|         KernAux_Memmap_free(memmap); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void test_examples_1_and_2(const KernAux_Memmap memmap) | ||||
| { | ||||
|     KernAux_Memmap_Node node = memmap->root_node; | ||||
| 
 | ||||
|     assert(node); | ||||
|     assert(node->mem_start == 0x0); | ||||
|     assert(node->mem_size  == 0xffffffffffffffff); | ||||
|     assert(node->mem_end   == 0xffffffffffffffff); | ||||
|     assert(node->tag == NULL); | ||||
|     assert(node->next == NULL); | ||||
| 
 | ||||
|     node = node->children; | ||||
|     assert(node); | ||||
|     assert(node->mem_start == 0x0); | ||||
|     assert(node->mem_size  == 654336); | ||||
|     assert(node->mem_end   == 0x9fbff); | ||||
|     assert(strcmp(node->tag, "available") == 0); | ||||
|     assert(node->children  == NULL); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0x0)); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0x9fbff)); | ||||
| 
 | ||||
|     node = node->next; | ||||
|     assert(node); | ||||
|     assert(node->mem_start == 0x9fc00); | ||||
|     assert(node->mem_size  == 1024); | ||||
|     assert(node->mem_end   == 0x9ffff); | ||||
|     assert(strcmp(node->tag, "reserved") == 0); | ||||
|     assert(node->children  == NULL); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0x9fc00)); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0x9ffff)); | ||||
| 
 | ||||
|     node = node->next; | ||||
|     assert(node); | ||||
|     assert(node->mem_start == 0xf0000); | ||||
|     assert(node->mem_size  == 65536); | ||||
|     assert(node->mem_end   == 0xfffff); | ||||
|     assert(strcmp(node->tag, "reserved") == 0); | ||||
|     assert(node->children  == NULL); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0xf0000)); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0xfffff)); | ||||
| 
 | ||||
|     node = node->next; | ||||
|     assert(node); | ||||
|     assert(node->mem_start == 0x100000); | ||||
|     assert(node->mem_size  == 133038080); | ||||
|     assert(node->mem_end   == 0x7fdffff); | ||||
|     assert(strcmp(node->tag, "available") == 0); | ||||
|     assert(node->children  == NULL); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0x100000)); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0x7fdffff)); | ||||
| 
 | ||||
|     node = node->next; | ||||
|     assert(node); | ||||
|     assert(node->mem_start == 0x7fe0000); | ||||
|     assert(node->mem_size  == 131072); | ||||
|     assert(node->mem_end   == 0x7ffffff); | ||||
|     assert(strcmp(node->tag, "reserved") == 0); | ||||
|     assert(node->children  == NULL); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0x7fe0000)); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0x7ffffff)); | ||||
| 
 | ||||
|     node = node->next; | ||||
|     assert(node); | ||||
|     assert(node->mem_start == 0xfffc0000); | ||||
|     assert(node->mem_size  == 262144); | ||||
|     assert(node->mem_end   == 0xffffffff); | ||||
|     assert(strcmp(node->tag, "reserved") == 0); | ||||
|     assert(node->children  == NULL); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0xfffc0000)); | ||||
|     assert(node == KernAux_Memmap_node_by_addr(memmap, 0xffffffff)); | ||||
| 
 | ||||
|     node = node->next; | ||||
|     assert(node == NULL); | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alex Kotov
						Alex Kotov