Revert "Remove memory map"

This reverts commit 1e749c5c89.
This commit is contained in:
Alex Kotov 2023-01-06 15:56:18 +04:00
parent 1e749c5c89
commit af165909db
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
19 changed files with 876 additions and 3 deletions

View File

@ -94,6 +94,7 @@ jobs:
- without: 'ntoa'
dependencies: '--without-printf --without-units'
- without: 'printf'
- without: 'memmap'
steps:
- uses: actions/checkout@v2
- name: autogen

View File

@ -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>

View File

@ -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 \

View File

@ -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

View File

@ -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
View File

@ -7,6 +7,7 @@
/macro_container_of
/macro_packing
/macro_static_test
/memmap
/multiboot2_header_macro
/ntoa
/pfa

View File

@ -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
View 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);
}

View File

@ -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 \

View File

@ -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
View 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

View File

@ -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

View File

@ -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
View 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("}");
}
}

View 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
View File

@ -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

View File

@ -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
View 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);
}

View 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);
}