Merge branch 'master' into paging

This commit is contained in:
Alex Kotov 2022-12-11 17:48:34 +04:00
commit 3eb0acf22b
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
26 changed files with 896 additions and 194 deletions

3
.gitignore vendored
View File

@ -79,11 +79,14 @@
/examples/assert
/examples/cmdline
/examples/generic_display
/examples/generic_malloc
/examples/generic_mutex
/examples/macro_bits
/examples/macro_cast
/examples/macro_container_of
/examples/macro_packing
/examples/macro_static_test
/examples/memmap
/examples/multiboot2_header_macro
/examples/ntoa

View File

@ -1,3 +1,15 @@
2022-12-11 Alex Kotov <kotovalexarian@gmail.com>
* include/kernaux/macro.h: Macro "KERNAUX_STATIC_TEST" has been added
2022-12-10 Alex Kotov <kotovalexarian@gmail.com>
* include/kernaux/macro.h: Macros "KERNAUX_CAST_(VAR|CONST)" have been added
2022-12-09 Alex Kotov <kotovalexarian@gmail.com>
* include/kernaux/generic/display.h: The header has been added
2022-12-08 Alex Kotov <kotovalexarian@gmail.com>
* include/kernaux/*.h: Definition "KERNAUX_BITFIELDS" has been added

View File

@ -31,6 +31,7 @@ lib_LTLIBRARIES = libkernaux.la
libkernaux_la_LIBADD =
libkernaux_la_SOURCES = \
src/assert.c \
src/generic/display.c \
src/generic/malloc.c \
src/generic/mutex.c
@ -47,7 +48,7 @@ endif
#######
if WITH_ARCH_I386
libkernaux_la_SOURCES += src/arch/i386.c
libkernaux_la_SOURCES += src/arch/i386/idt.c
endif
#######

View File

@ -42,13 +42,17 @@ zero). Work-in-progress APIs can change at any time.
* [Feature macros](/include/kernaux/version.h.in) (*work in progress*)
* [Macros](/include/kernaux/macro.h) (*non-breaking since* **0.6.0**)
* [Example: packing](/examples/macro_packing.c)
* [Example: CONTAINER_OF](/examples/macro_container_of.c)
* [Example: CAST\_\*](/examples/macro_cast.c);
* [Example: CONTAINER\_OF](/examples/macro_container_of.c)
* [Example: BITS](/examples/macro_bits.c)
* [Example: STATIC\_TEST\*](/examples/macro_static_test.c)
* [Assertions](/include/kernaux/assert.h) (*non-breaking since* **0.4.0**)
* [Example: Assert](/examples/assert.c)
* [Example: Panic](/examples/panic.c)
* Stack trace *(planned)*
* Generic types
* [Display](/include/kernaux/generic/display.h) (*non-breaking since* **?.?.?**)
* [Example](/examples/generic_display.c)
* [Memory allocator](/include/kernaux/generic/malloc.h) (*non-breaking since* **0.5.0**)
* [Example](/examples/generic_malloc.c)
* [Mutex](/include/kernaux/generic/mutex.h) (*non-breaking since* **0.5.0**)

View File

@ -331,7 +331,7 @@ AC_HEADER_STDBOOL
AS_IF([test "$enable_checks" = yes -a "$ac_cv_header_stdbool_h" != yes],
[AC_MSG_ERROR([the header is required])])
AC_CHECK_HEADERS([stdarg.h stddef.h stdint.h],,
AC_CHECK_HEADERS([limits.h stdarg.h stddef.h stdint.h],,
[AC_MSG_ERROR([the headers are required])])
AS_IF([test "$enable_checks" = yes],

View File

@ -21,6 +21,14 @@ cmdline_LDADD = $(top_builddir)/libkernaux.la
cmdline_SOURCES = main.c cmdline.c
endif
###################
# generic_display #
###################
TESTS += generic_display
generic_display_LDADD = $(top_builddir)/libkernaux.la
generic_display_SOURCES = main.c generic_display.c
##################
# generic_malloc #
##################
@ -45,6 +53,14 @@ TESTS += macro_bits
macro_bits_LDADD = $(top_builddir)/libkernaux.la
macro_bits_SOURCES = main.c macro_bits.c
##############
# macro_cast #
##############
TESTS += macro_cast
macro_cast_LDADD = $(top_builddir)/libkernaux.la
macro_cast_SOURCES = main.c macro_cast.c
######################
# macro_container_of #
######################
@ -61,6 +77,14 @@ TESTS += macro_packing
macro_packing_LDADD = $(top_builddir)/libkernaux.la
macro_packing_SOURCES = main.c macro_packing.c
#####################
# macro_static_test #
#####################
TESTS += macro_static_test
macro_static_test_LDADD = $(top_builddir)/libkernaux.la
macro_static_test_SOURCES = main.c macro_static_test.c
##########
# memmap #
##########

115
examples/generic_display.c Normal file
View File

@ -0,0 +1,115 @@
//==============
// my_display.c
//==============
// To not always use macro "KERNAUX_PROTECTED_FIELD" around the names of
// structure fields you may define "KERNAUX_ACCESS_PROTECTED" before including
// any other headers, but ONLY in the file where you implement a generic type.
//
#define KERNAUX_ACCESS_PROTECTED
//==============
// my_display.h
//==============
#include <kernaux/generic/display.h>
#include <stddef.h>
typedef struct MyDisplay {
struct KernAux_Display display;
char *buffer, *cursor;
size_t capacity;
} *MyDisplay;
struct MyDisplay MyDisplay_create();
//==============
// my_display.c
//==============
#include <assert.h>
#include <kernaux/generic/display.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CAP_FREE (1024)
#define CAP_INCR (2 * (CAP_FREE))
static void MyDisplay_putc(void *display, char c);
void MyDisplay_vprintf(void *display, const char *format, va_list va);
static void MyDisplay_realloc(MyDisplay my_display);
struct MyDisplay MyDisplay_create()
{
char *const buffer = malloc(CAP_INCR);
if (!buffer) abort();
return (struct MyDisplay){
.display = {
.putc = MyDisplay_putc,
.vprintf = MyDisplay_vprintf,
},
.buffer = buffer,
.cursor = buffer,
.capacity = CAP_INCR,
};
}
void MyDisplay_putc(void *display, char c)
{
const MyDisplay my_display = display;
MyDisplay_realloc(my_display);
*(my_display->cursor++) = c;
}
void MyDisplay_vprintf(void *display, const char *format, va_list va)
{
const MyDisplay my_display = display;
MyDisplay_realloc(my_display);
size_t left =
my_display->buffer + my_display->capacity - my_display->cursor;
const int delta = vsnprintf(my_display->cursor, left, format, va);
if (delta < 0) abort();
my_display->cursor += delta;
}
void MyDisplay_realloc(const MyDisplay my_display)
{
size_t left =
my_display->buffer + my_display->capacity - my_display->cursor;
if (left < CAP_FREE) {
my_display->buffer =
realloc(my_display->buffer, my_display->capacity + CAP_INCR);
if (!my_display->buffer) abort();
my_display->capacity += CAP_INCR;
}
}
//========
// main.c
//========
void example_main()
{
struct MyDisplay my_display = MyDisplay_create();
KernAux_Display_putc(&my_display.display, '@');
KernAux_Display_print(&my_display.display, "print");
KernAux_Display_println(&my_display.display, "println");
KernAux_Display_write(&my_display.display, "write!!!", 5);
KernAux_Display_writeln(&my_display.display, "writeln!!!", 7);
KernAux_Display_printf(&my_display.display, "printf(%d)", 123);
KernAux_Display_printlnf(&my_display.display, "printfln(%d)", 123);
assert(
strcmp(
my_display.buffer,
"@printprintln\nwritewriteln\nprintf(123)printfln(123)\n"
) == 0
);
}

25
examples/macro_cast.c Normal file
View File

@ -0,0 +1,25 @@
#include <kernaux/macro.h>
#include <assert.h>
#include <stdint.h>
void example_main()
{
const uint32_t value = 123;
// const unsigned long ul = (unsigned long)value;
KERNAUX_CAST_CONST(unsigned long, ul, value);
assert(ul == 123);
// unsigned long long ull = (unsigned long long)value;
KERNAUX_CAST_VAR(unsigned long long, ull, value);
assert(ull == 123);
// const [signed] long sl = ([signed] long)value;
KERNAUX_CAST_CONST(long, sl, value);
assert(sl == 123);
// [signed] long long sll = ([signed] long long)value;
KERNAUX_CAST_VAR(long long, sll, value);
assert(sll == 123);
}

View File

@ -0,0 +1,28 @@
#include <kernaux/macro.h>
#include <stdint.h>
KERNAUX_STATIC_TEST(uint8_t_size, sizeof(uint8_t) == 1);
KERNAUX_STATIC_TEST(uint16_t_size, sizeof(uint16_t) == 2);
KERNAUX_STATIC_TEST(uint32_t_size, sizeof(uint32_t) == 4);
KERNAUX_STATIC_TEST(uint64_t_size, sizeof(uint64_t) == 8);
#include <kernaux/macro/packing_start.run>
struct Foo {
uint8_t a;
uint32_t b;
} KERNAUX_PACKED;
KERNAUX_STATIC_TEST_STRUCT_SIZE(Foo, 5);
union Bar {
uint8_t a;
uint16_t b;
} KERNAUX_PACKED;
KERNAUX_STATIC_TEST_UNION_SIZE(Bar, 2);
#include <kernaux/macro/packing_end.run>
void example_main() {}

View File

@ -9,6 +9,7 @@ nobase_include_HEADERS = \
kernaux/macro/packing_start.run \
kernaux/macro/packing_end.run \
kernaux/version.h \
kernaux/generic/display.h \
kernaux/generic/malloc.h \
kernaux/generic/mutex.h
@ -17,7 +18,7 @@ nobase_include_HEADERS = \
########
if WITH_ARCH_I386
nobase_include_HEADERS += kernaux/arch/i386.h
nobase_include_HEADERS += kernaux/arch/i386.h kernaux/arch/i386-idt.h
endif
if WITH_ARCH_RISCV64
nobase_include_HEADERS += kernaux/arch/riscv64.h

View File

@ -0,0 +1,62 @@
#ifndef KERNAUX_INCLUDED_ARCH_I386_IDT
#define KERNAUX_INCLUDED_ARCH_I386_IDT
#ifdef __cplusplus
extern "C" {
#endif
#include <kernaux/macro.h>
#include <stdint.h>
#include <kernaux/macro/packing_start.run>
/**
* @brief Interrupt Descriptor Table entry
*
* @see https://en.wikibooks.org/wiki/X86_Assembly/Advanced_Interrupts#The_Interrupt_Descriptor_Table
*/
typedef struct KernAux_Arch_I386_IDTE {
uint16_t offset_low;
uint16_t selector;
uint8_t _;
uint8_t flags;
uint16_t offset_high;
}
KERNAUX_PACKED
KERNAUX_ALIGNED(8)
*KernAux_Arch_I386_IDTE;
KERNAUX_STATIC_TEST_STRUCT_SIZE(KernAux_Arch_I386_IDTE, 8);
#include <kernaux/macro/packing_end.run>
void KernAux_Arch_I386_IDTE_init_intr(
KernAux_Arch_I386_IDTE idte,
uint32_t offset,
uint16_t cs_selector,
uint8_t dpl
);
void KernAux_Arch_I386_IDTE_init_task(
KernAux_Arch_I386_IDTE idte,
uint16_t tss_selector,
uint8_t dpl
);
void KernAux_Arch_I386_IDTE_init_trap(
KernAux_Arch_I386_IDTE idte,
uint32_t offset,
uint16_t cs_selector,
uint8_t dpl
);
uint32_t KernAux_Arch_I386_IDTE_offset(KernAux_Arch_I386_IDTE idte);
uint8_t KernAux_Arch_I386_IDTE_dpl (KernAux_Arch_I386_IDTE idte);
void
KernAux_Arch_I386_IDTE_set_offset(KernAux_Arch_I386_IDTE idte, uint32_t offset);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -5,6 +5,7 @@
extern "C" {
#endif
#include <kernaux/arch/i386-idt.h>
#include <kernaux/arch/x86.h>
#include <kernaux/arch/x86-paging.h>
#include <kernaux/macro.h>
@ -92,25 +93,6 @@ KERNAUX_PACKED;
KERNAUX_STATIC_TEST_STRUCT_SIZE(KernAux_Arch_I386_DTE, 8);
// Interrupt descriptor table entry
// TODO: validate this according to spec
typedef struct KernAux_Arch_I386_IDTE {
uint16_t offset_low;
uint16_t selector;
uint8_t _zero0;
uint8_t flags;
uint16_t offset_high;
}
KERNAUX_PACKED
*KernAux_Arch_I386_IDTE;
KERNAUX_STATIC_TEST_STRUCT_SIZE(KernAux_Arch_I386_IDTE, 8);
void KernAux_Arch_I386_IDTE_set_offset(
KernAux_Arch_I386_IDTE idte,
uint32_t address
);
/**
* @brief Task state segment
* @see The manual, page 132, figure 7-1

View File

@ -0,0 +1,37 @@
#ifndef KERNAUX_INCLUDED_DISPLAY
#define KERNAUX_INCLUDED_DISPLAY
#ifdef __cplusplus
extern "C" {
#endif
#include <kernaux/macro.h>
#include <stdarg.h>
#include <stddef.h>
typedef void (*KernAux_Display_Putc )(void *display, char c);
typedef void (*KernAux_Display_Vprintf)(void *display, const char *format, va_list va);
typedef const struct KernAux_Display {
KernAux_Display_Putc KERNAUX_PROTECTED_FIELD(putc);
KernAux_Display_Vprintf KERNAUX_PROTECTED_FIELD(vprintf);
} *KernAux_Display;
void KernAux_Display_putc (KernAux_Display display, char c);
void KernAux_Display_print (KernAux_Display display, const char *s);
void KernAux_Display_println (KernAux_Display display, const char *s);
void KernAux_Display_write (KernAux_Display display, const char *data, size_t size);
void KernAux_Display_writeln (KernAux_Display display, const char *data, size_t size);
KERNAUX_PRINTF(2, 3)
void KernAux_Display_printf (KernAux_Display display, const char *format, ...);
KERNAUX_PRINTF(2, 3)
void KernAux_Display_printlnf (KernAux_Display display, const char *format, ...);
void KernAux_Display_vprintf (KernAux_Display display, const char *format, va_list va);
void KernAux_Display_vprintlnf(KernAux_Display display, const char *format, va_list va);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -50,19 +50,16 @@ extern "C" {
* Static assertions *
*********************/
#define KERNAUX_STATIC_TEST(name, cond) \
KERNAUX_UNUSED \
static const int \
_kernaux_static_test_##name[(cond) ? 1 : -1]
#define KERNAUX_STATIC_TEST_STRUCT_SIZE(name, size) \
KERNAUX_UNUSED \
static const int \
_kernaux_static_test_struct_size_##name[ \
sizeof(struct name) == (size) ? 1 : -1 \
]
KERNAUX_STATIC_TEST(struct_size_##name, sizeof(struct name) == (size))
#define KERNAUX_STATIC_TEST_UNION_SIZE(name, size) \
KERNAUX_UNUSED \
static const int \
_kernaux_static_test_union_size_##name[ \
sizeof(union name) == (size) ? 1 : -1 \
]
KERNAUX_STATIC_TEST(union_size_##name, sizeof(union name) == (size))
/*****************
* Simple values *
@ -84,6 +81,19 @@ _kernaux_static_test_union_size_##name[ \
#define KERNAUX_BITS32(n) ((uint32_t)(((uint32_t)1) << (n)))
#define KERNAUX_BITS64(n) ((uint64_t)(((uint64_t)1) << (n)))
/*********************
* Safe type casting *
*********************/
#define KERNAUX_CAST_VAR(type, name, value) \
KERNAUX_STATIC_TEST(cast_pos_##name, sizeof(value) <= sizeof(type)); \
KERNAUX_STATIC_TEST(cast_neg_##name, sizeof(-(value)) <= sizeof(type)); \
type name = (type)(value); \
do {} while (0)
#define KERNAUX_CAST_CONST(type, name, value) \
KERNAUX_CAST_VAR(const type, name, value)
#ifdef __cplusplus
}
#endif

View File

@ -6,6 +6,7 @@ extern "C" {
#endif
#include <kernaux/macro.h>
#include <kernaux/generic/display.h>
@comment_line_memmap@#include <kernaux/memmap.h>
#include <kernaux/multiboot2/header_macro.h>
@ -789,12 +790,12 @@ bool KernAux_Multiboot2_ITag_ImageLoadBasePhysAddr_is_valid(
void KernAux_Multiboot2_Header_print(
const struct KernAux_Multiboot2_Header *multiboot2_header,
void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2)
KernAux_Display display
);
void KernAux_Multiboot2_HTagBase_print(
const struct KernAux_Multiboot2_HTagBase *tag_base,
void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2)
KernAux_Display display
);
/*******************************
@ -803,32 +804,32 @@ void KernAux_Multiboot2_HTagBase_print(
void KernAux_Multiboot2_Info_print(
const struct KernAux_Multiboot2_Info *multiboot2_info,
void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2)
KernAux_Display display
);
void KernAux_Multiboot2_ITagBase_print(
const struct KernAux_Multiboot2_ITagBase *tag_base,
void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2)
KernAux_Display display
);
void KernAux_Multiboot2_ITag_BootCmdLine_print(
const struct KernAux_Multiboot2_ITag_BootCmdLine *tag,
void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2)
KernAux_Display display
);
void KernAux_Multiboot2_ITag_BootLoaderName_print(
const struct KernAux_Multiboot2_ITag_BootLoaderName *tag,
void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2)
KernAux_Display display
);
void KernAux_Multiboot2_ITag_MemoryMap_print(
const struct KernAux_Multiboot2_ITag_MemoryMap *tag,
void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2)
KernAux_Display display
);
void KernAux_Multiboot2_ITag_ELFSymbols_print(
const struct KernAux_Multiboot2_ITag_ELFSymbols *tag,
void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2)
KernAux_Display display
);
#ifdef __cplusplus

View File

@ -20,7 +20,8 @@ CPPCHECK_INC = \
-I$(top_srcdir)/include
CPPCHECK_SUPPRESS = \
--suppress='unusedStructMember:$(top_srcdir)/examples/multiboot2_header_macro.c' \
--suppress='constArgument:$(top_srcdir)/examples/macro_cast.c' \
--suppress='unusedStructMember:$(top_srcdir)/examples/*.c' \
--suppress='unusedStructMember:$(top_srcdir)/tests/test_multiboot2_info_*.c'
CPPCHECK_PATHS = \

View File

@ -1,14 +0,0 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <kernaux/arch/i386.h>
void KernAux_Arch_I386_IDTE_set_offset(
const KernAux_Arch_I386_IDTE idte,
const uint32_t address
)
{
idte->offset_low = 0xFFFF & address;
idte->offset_high = 0xFFFF & (address >> 16);
}

74
src/arch/i386/idt.c Normal file
View File

@ -0,0 +1,74 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <kernaux/arch/i386.h>
#include <kernaux/assert.h>
#include <string.h>
#define DPL (0x60u & (dpl << 5))
void KernAux_Arch_I386_IDTE_init_intr(
const KernAux_Arch_I386_IDTE idte,
const uint32_t offset,
const uint16_t cs_selector,
const uint8_t dpl
) {
KERNAUX_ASSERT(idte);
memset(idte, 0, sizeof(*idte));
KernAux_Arch_I386_IDTE_set_offset(idte, offset);
idte->selector = cs_selector;
idte->flags |= 0x80u | DPL | 0xeu; // 1-00-01110
}
void KernAux_Arch_I386_IDTE_init_task(
const KernAux_Arch_I386_IDTE idte,
const uint16_t tss_selector,
const uint8_t dpl
) {
KERNAUX_ASSERT(idte);
memset(idte, 0, sizeof(*idte));
idte->selector = tss_selector;
idte->flags |= 0x80u | DPL | 0x5u; // 1-00-00101
}
void KernAux_Arch_I386_IDTE_init_trap(
const KernAux_Arch_I386_IDTE idte,
const uint32_t offset,
const uint16_t cs_selector,
const uint8_t dpl
) {
KERNAUX_ASSERT(idte);
memset(idte, 0, sizeof(*idte));
KernAux_Arch_I386_IDTE_set_offset(idte, offset);
idte->selector = cs_selector;
idte->flags |= 0x80u | DPL | 0xfu; // 1-00-01111
}
uint32_t KernAux_Arch_I386_IDTE_offset(const KernAux_Arch_I386_IDTE idte)
{
KERNAUX_ASSERT(idte);
return (idte->offset_high << 16) | idte->offset_low;
}
uint8_t KernAux_Arch_I386_IDTE_dpl(const KernAux_Arch_I386_IDTE idte)
{
KERNAUX_ASSERT(idte);
return 3 & (idte->flags >> 5);
}
void KernAux_Arch_I386_IDTE_set_offset(
const KernAux_Arch_I386_IDTE idte,
const uint32_t offset
) {
KERNAUX_ASSERT(idte);
idte->offset_low = 0xffffu & offset;
idte->offset_high = 0xffffu & (offset >> 16);
}

115
src/generic/display.c Normal file
View File

@ -0,0 +1,115 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <kernaux/assert.h>
#include <kernaux/generic/display.h>
#include <stdarg.h>
#include <stddef.h>
void KernAux_Display_putc(const KernAux_Display display, const char c)
{
KERNAUX_ASSERT(display);
KERNAUX_ASSERT(display->putc);
// Inherited implementation
display->putc((void*)display, c);
}
void KernAux_Display_print(const KernAux_Display display, const char *const s)
{
KERNAUX_ASSERT(display);
KERNAUX_ASSERT(display->putc);
// Default implementation
for (const char *c = s; *c; ++c) display->putc((void*)display, *c);
}
void KernAux_Display_println(const KernAux_Display display, const char *const s)
{
KERNAUX_ASSERT(display);
KERNAUX_ASSERT(display->putc);
// Default implementation
KernAux_Display_print(display, s);
display->putc((void*)display, '\n');
}
void KernAux_Display_write(
const KernAux_Display display,
const char *const data,
const size_t size
) {
KERNAUX_ASSERT(display);
KERNAUX_ASSERT(display->putc);
// Default implementation
for (size_t i = 0; i < size; ++i) display->putc((void*)display, data[i]);
}
void KernAux_Display_writeln(
const KernAux_Display display,
const char *const data,
const size_t size
) {
KERNAUX_ASSERT(display);
KERNAUX_ASSERT(display->putc);
// Default implementation
KernAux_Display_write(display, data, size);
display->putc((void*)display, '\n');
}
void KernAux_Display_printf(
const KernAux_Display display,
const char *const format,
...
) {
KERNAUX_ASSERT(display);
// Default implementation
va_list va;
va_start(va, format);
KernAux_Display_vprintf(display, format, va);
va_end(va);
}
void KernAux_Display_printlnf(
const KernAux_Display display,
const char *const format,
...
) {
KERNAUX_ASSERT(display);
// Default implementation
va_list va;
va_start(va, format);
KernAux_Display_vprintlnf(display, format, va);
va_end(va);
}
void KernAux_Display_vprintf(
const KernAux_Display display,
const char *const format,
va_list va
) {
KERNAUX_ASSERT(display);
KERNAUX_ASSERT(display->vprintf);
// Inherited implementation
display->vprintf((void*)display, format, va);
}
void KernAux_Display_vprintlnf(
const KernAux_Display display,
const char *const format,
va_list va
) {
KERNAUX_ASSERT(display);
KERNAUX_ASSERT(display->putc);
// Default implementation
KernAux_Display_vprintf(display, format, va);
display->putc((void*)display, '\n');
}

View File

@ -3,27 +3,36 @@
#endif
#include <kernaux/assert.h>
#include <kernaux/generic/display.h>
#include <kernaux/macro.h>
#include <kernaux/multiboot2.h>
#include <stddef.h>
#include <stdint.h>
#define PRINTLN(s) KernAux_Display_println(display, s)
#define PRINTLNF(format, ...) \
KernAux_Display_printlnf(display, format, __VA_ARGS__)
void KernAux_Multiboot2_Header_print(
const struct KernAux_Multiboot2_Header *const multiboot2_header,
void (*const printf)(const char *format, ...)
const KernAux_Display display
) {
KERNAUX_ASSERT(multiboot2_header);
KERNAUX_ASSERT(printf);
KERNAUX_ASSERT(display);
printf("Multiboot 2 header\n");
printf(" magic: %u\n", multiboot2_header->magic);
printf(
" arch: %u (%s)\n",
KERNAUX_CAST_CONST(unsigned long, magic, multiboot2_header->magic);
KERNAUX_CAST_CONST(unsigned long, total_size, multiboot2_header->total_size);
KERNAUX_CAST_CONST(unsigned long, checksum, multiboot2_header->checksum);
PRINTLN("Multiboot 2 header");
PRINTLNF(" magic: %lu", magic);
PRINTLNF(" arch: %u (%s)",
multiboot2_header->arch,
KernAux_Multiboot2_Header_Arch_to_str(multiboot2_header->arch)
);
printf(" size: %u\n", multiboot2_header->total_size);
printf(" checksum: %u\n", multiboot2_header->checksum);
PRINTLNF(" size: %lu", total_size);
PRINTLNF(" checksum: %lu", checksum);
const struct KernAux_Multiboot2_HTagBase *tag_base =
(struct KernAux_Multiboot2_HTagBase*)
@ -35,7 +44,7 @@ void KernAux_Multiboot2_Header_print(
{
if (!KernAux_Multiboot2_HTagBase_is_valid(tag_base)) return;
KernAux_Multiboot2_HTagBase_print(tag_base, printf);
KernAux_Multiboot2_HTagBase_print(tag_base, display);
tag_base = KERNAUX_MULTIBOOT2_HTAG_NEXT(tag_base);
}
@ -43,23 +52,23 @@ void KernAux_Multiboot2_Header_print(
void KernAux_Multiboot2_HTagBase_print(
const struct KernAux_Multiboot2_HTagBase *const tag_base,
void (*const printf)(const char *format, ...)
const KernAux_Display display
) {
KERNAUX_ASSERT(tag_base);
KERNAUX_ASSERT(printf);
KERNAUX_ASSERT(display);
if (!KernAux_Multiboot2_HTagBase_is_valid(tag_base)) return;
printf("Multiboot 2 header tag\n");
KERNAUX_CAST_CONST(unsigned long, flags, tag_base->flags);
KERNAUX_CAST_CONST(unsigned long, size, tag_base->size);
printf(
" type: %u (%s)\n",
PRINTLN("Multiboot 2 header tag");
PRINTLNF(" type: %u (%s)",
tag_base->type,
KernAux_Multiboot2_HTag_to_str(tag_base->type)
);
printf(" flags: %u\n", tag_base->flags);
printf(" size: %u\n", tag_base->size);
PRINTLNF(" flags: %lu", flags);
PRINTLNF(" size: %lu", size);
switch (tag_base->type) {
case KERNAUX_MULTIBOOT2_HTAG_NONE:

View File

@ -3,21 +3,32 @@
#endif
#include <kernaux/assert.h>
#include <kernaux/macro.h>
#include <kernaux/multiboot2.h>
#include <stddef.h>
#include <stdint.h>
// TODO: create macro for this
#define INT_IF(a, b) (sizeof(int) == sizeof(long) ? (a) : (b))
#define PRINTLN(s) KernAux_Display_println(display, s)
#define PRINTLNF(format, ...) \
KernAux_Display_printlnf(display, format, __VA_ARGS__)
void KernAux_Multiboot2_Info_print(
const struct KernAux_Multiboot2_Info *const multiboot2_info,
void (*const printf)(const char *format, ...)
const KernAux_Display display
) {
KERNAUX_ASSERT(multiboot2_info);
KERNAUX_ASSERT(printf);
KERNAUX_ASSERT(display);
printf("Multiboot 2 info\n");
printf(" size: %u\n", multiboot2_info->total_size);
printf(" reserved1: %u\n", multiboot2_info->reserved1);
KERNAUX_CAST_CONST(unsigned long, total_size, multiboot2_info->total_size);
KERNAUX_CAST_CONST(unsigned long, reserved1, multiboot2_info->reserved1);
PRINTLN("Multiboot 2 info");
PRINTLNF(" size: %lu", total_size);
PRINTLNF(" reserved1: %lu", reserved1);
const struct KernAux_Multiboot2_ITagBase *tag_base =
(struct KernAux_Multiboot2_ITagBase*)
@ -29,7 +40,7 @@ void KernAux_Multiboot2_Info_print(
{
if (!KernAux_Multiboot2_ITagBase_is_valid(tag_base)) return;
KernAux_Multiboot2_ITagBase_print(tag_base, printf);
KernAux_Multiboot2_ITagBase_print(tag_base, display);
tag_base = KERNAUX_MULTIBOOT2_ITAG_NEXT(tag_base);
}
@ -37,22 +48,22 @@ void KernAux_Multiboot2_Info_print(
void KernAux_Multiboot2_ITagBase_print(
const struct KernAux_Multiboot2_ITagBase *const tag_base,
void (*const printf)(const char *format, ...)
const KernAux_Display display
) {
KERNAUX_ASSERT(tag_base);
KERNAUX_ASSERT(printf);
KERNAUX_ASSERT(display);
if (!KernAux_Multiboot2_ITagBase_is_valid(tag_base)) return;
printf("Multiboot 2 info tag\n");
PRINTLN("Multiboot 2 info tag");
printf(
" type: %u (%s)\n",
PRINTLNF(" type: %u (%s)",
tag_base->type,
KernAux_Multiboot2_ITag_to_str(tag_base->type)
);
printf(" size: %u\n", tag_base->size);
KERNAUX_CAST_CONST(unsigned long, size, tag_base->size);
PRINTLNF(" size: %lu", size);
switch (tag_base->type) {
case KERNAUX_MULTIBOOT2_ITAG_NONE:
@ -60,13 +71,13 @@ void KernAux_Multiboot2_ITagBase_print(
case KERNAUX_MULTIBOOT2_ITAG_BOOT_CMD_LINE:
KernAux_Multiboot2_ITag_BootCmdLine_print(
(struct KernAux_Multiboot2_ITag_BootCmdLine*)tag_base,
printf
display
);
break;
case KERNAUX_MULTIBOOT2_ITAG_BOOT_LOADER_NAME:
KernAux_Multiboot2_ITag_BootLoaderName_print(
(struct KernAux_Multiboot2_ITag_BootLoaderName*)tag_base,
printf
display
);
break;
case KERNAUX_MULTIBOOT2_ITAG_MODULE:
@ -74,9 +85,12 @@ void KernAux_Multiboot2_ITagBase_print(
const struct KernAux_Multiboot2_ITag_Module *const tag_module =
(struct KernAux_Multiboot2_ITag_Module*)tag_base;
printf(" start: %u\n", tag_module->mod_start);
printf(" end: %u\n", tag_module->mod_end);
printf(" cmdline: %s\n", KERNAUX_MULTIBOOT2_DATA(tag_module));
KERNAUX_CAST_CONST(unsigned long, mod_start, tag_module->mod_start);
KERNAUX_CAST_CONST(unsigned long, mod_end, tag_module->mod_end);
PRINTLNF(" start: %lu", mod_start);
PRINTLNF(" end: %lu", mod_end);
PRINTLNF(" cmdline: %s", KERNAUX_MULTIBOOT2_DATA(tag_module));
}
break;
case KERNAUX_MULTIBOOT2_ITAG_BASIC_MEMORY_INFO:
@ -84,8 +98,11 @@ void KernAux_Multiboot2_ITagBase_print(
const struct KernAux_Multiboot2_ITag_BasicMemoryInfo *const tag_bmi =
(struct KernAux_Multiboot2_ITag_BasicMemoryInfo*)tag_base;
printf(" mem lower: %u\n", tag_bmi->mem_lower);
printf(" mem upper: %u\n", tag_bmi->mem_upper);
KERNAUX_CAST_CONST(unsigned long, mem_lower, tag_bmi->mem_lower);
KERNAUX_CAST_CONST(unsigned long, mem_upper, tag_bmi->mem_upper);
PRINTLNF(" mem lower: %lu", mem_lower);
PRINTLNF(" mem upper: %lu", mem_upper);
}
break;
case KERNAUX_MULTIBOOT2_ITAG_BIOS_BOOT_DEVICE:
@ -93,15 +110,19 @@ void KernAux_Multiboot2_ITagBase_print(
const struct KernAux_Multiboot2_ITag_BIOSBootDevice *const tag_bbd =
(struct KernAux_Multiboot2_ITag_BIOSBootDevice*)tag_base;
printf(" bios dev: %u\n", tag_bbd->bios_dev);
printf(" partition: %u\n", tag_bbd->partition);
printf(" sub_partition: %u\n", tag_bbd->sub_partition);
KERNAUX_CAST_CONST(unsigned long, bios_dev, tag_bbd->bios_dev);
KERNAUX_CAST_CONST(unsigned long, partition, tag_bbd->partition);
KERNAUX_CAST_CONST(unsigned long, sub_partition, tag_bbd->sub_partition);
PRINTLNF(" bios dev: %lu", bios_dev);
PRINTLNF(" partition: %lu", partition);
PRINTLNF(" sub_partition: %lu", sub_partition);
}
break;
case KERNAUX_MULTIBOOT2_ITAG_MEMORY_MAP:
KernAux_Multiboot2_ITag_MemoryMap_print(
(struct KernAux_Multiboot2_ITag_MemoryMap*)tag_base,
printf
display
);
break;
case KERNAUX_MULTIBOOT2_ITAG_VBE_INFO:
@ -109,10 +130,15 @@ void KernAux_Multiboot2_ITagBase_print(
const struct KernAux_Multiboot2_ITag_VBEInfo *const tag_vbe =
(struct KernAux_Multiboot2_ITag_VBEInfo*)tag_base;
printf(" VBE mode: %hu\n", tag_vbe->vbe_mode);
printf(" VBE interface seg: %hu\n", tag_vbe->vbe_interface_seg);
printf(" VBE interface off: %hu\n", tag_vbe->vbe_interface_off);
printf(" VBE interface len: %hu\n", tag_vbe->vbe_interface_len);
KERNAUX_CAST_CONST(unsigned long, vbe_mode, tag_vbe->vbe_mode);
KERNAUX_CAST_CONST(unsigned long, vbe_interface_seg, tag_vbe->vbe_interface_seg);
KERNAUX_CAST_CONST(unsigned long, vbe_interface_off, tag_vbe->vbe_interface_off);
KERNAUX_CAST_CONST(unsigned long, vbe_interface_len, tag_vbe->vbe_interface_len);
PRINTLNF(" VBE mode: %lu", vbe_mode);
PRINTLNF(" VBE interface seg: %lu", vbe_interface_seg);
PRINTLNF(" VBE interface off: %lu", vbe_interface_off);
PRINTLNF(" VBE interface len: %lu", vbe_interface_len);
}
break;
case KERNAUX_MULTIBOOT2_ITAG_FRAMEBUFFER_INFO:
@ -120,19 +146,27 @@ void KernAux_Multiboot2_ITagBase_print(
const struct KernAux_Multiboot2_ITag_FramebufferInfo *const tag_fb =
(struct KernAux_Multiboot2_ITag_FramebufferInfo*)tag_base;
printf(" framebuffer addr: %llu\n", tag_fb->framebuffer_addr);
printf(" framebuffer pitch: %u\n", tag_fb->framebuffer_pitch);
printf(" framebuffer width: %u\n", tag_fb->framebuffer_width);
printf(" framebuffer height: %u\n", tag_fb->framebuffer_height);
printf(" framebuffer bpp: %u\n", tag_fb->framebuffer_bpp);
printf(" framebuffer type: %u\n", tag_fb->framebuffer_type);
printf(" reserved1: %u\n", tag_fb->reserved1);
KERNAUX_CAST_CONST(unsigned long long, framebuffer_addr, tag_fb->framebuffer_addr);
KERNAUX_CAST_CONST(unsigned long, framebuffer_pitch, tag_fb->framebuffer_pitch);
KERNAUX_CAST_CONST(unsigned long, framebuffer_width, tag_fb->framebuffer_width);
KERNAUX_CAST_CONST(unsigned long, framebuffer_height, tag_fb->framebuffer_height);
KERNAUX_CAST_CONST(unsigned long, framebuffer_bpp, tag_fb->framebuffer_bpp);
KERNAUX_CAST_CONST(unsigned long, framebuffer_type, tag_fb->framebuffer_type);
KERNAUX_CAST_CONST(unsigned long, reserved1, tag_fb->reserved1);
PRINTLNF(" framebuffer addr: %llu", framebuffer_addr);
PRINTLNF(" framebuffer pitch: %lu", framebuffer_pitch);
PRINTLNF(" framebuffer width: %lu", framebuffer_width);
PRINTLNF(" framebuffer height: %lu", framebuffer_height);
PRINTLNF(" framebuffer bpp: %lu", framebuffer_bpp);
PRINTLNF(" framebuffer type: %lu", framebuffer_type);
PRINTLNF(" reserved1: %lu", reserved1);
}
break;
case KERNAUX_MULTIBOOT2_ITAG_ELF_SYMBOLS:
KernAux_Multiboot2_ITag_ELFSymbols_print(
(struct KernAux_Multiboot2_ITag_ELFSymbols*)tag_base,
printf
display
);
break;
case KERNAUX_MULTIBOOT2_ITAG_APM_TABLE:
@ -140,15 +174,25 @@ void KernAux_Multiboot2_ITagBase_print(
const struct KernAux_Multiboot2_ITag_APMTable *const tag_apm =
(struct KernAux_Multiboot2_ITag_APMTable*)tag_base;
printf(" version: %hu\n", tag_apm->version);
printf(" cseg: %hu\n", tag_apm->cseg);
printf(" offset: %u\n", tag_apm->offset);
printf(" cseg 16: %hu\n", tag_apm->cseg_16);
printf(" dseg: %hu\n", tag_apm->dseg);
printf(" flags: %hu\n", tag_apm->flags);
printf(" cseg len: %hu\n", tag_apm->cseg_len);
printf(" cseg 16 len: %hu\n", tag_apm->cseg_16_len);
printf(" dseg len: %hu\n", tag_apm->dseg_len);
KERNAUX_CAST_CONST(unsigned long, version, tag_apm->version);
KERNAUX_CAST_CONST(unsigned long, cseg, tag_apm->cseg);
KERNAUX_CAST_CONST(unsigned long, offset, tag_apm->offset);
KERNAUX_CAST_CONST(unsigned long, cseg_16, tag_apm->cseg_16);
KERNAUX_CAST_CONST(unsigned long, dseg, tag_apm->dseg);
KERNAUX_CAST_CONST(unsigned long, flags, tag_apm->flags);
KERNAUX_CAST_CONST(unsigned long, cseg_len, tag_apm->cseg_len);
KERNAUX_CAST_CONST(unsigned long, cseg_16_len, tag_apm->cseg_16_len);
KERNAUX_CAST_CONST(unsigned long, dseg_len, tag_apm->dseg_len);
PRINTLNF(" version: %lu", version);
PRINTLNF(" cseg: %lu", cseg);
PRINTLNF(" offset: %lu", offset);
PRINTLNF(" cseg 16: %lu", cseg_16);
PRINTLNF(" dseg: %lu", dseg);
PRINTLNF(" flags: %lu", flags);
PRINTLNF(" cseg len: %lu", cseg_len);
PRINTLNF(" cseg 16 len: %lu", cseg_16_len);
PRINTLNF(" dseg len: %lu", dseg_len);
}
break;
case KERNAUX_MULTIBOOT2_ITAG_EFI_32BIT_SYSTEM_TABLE_PTR:
@ -166,17 +210,22 @@ void KernAux_Multiboot2_ITagBase_print(
const struct KernAux_Multiboot2_ITag_SMBIOSTables *const tag_smbios =
(struct KernAux_Multiboot2_ITag_SMBIOSTables*)tag_base;
printf(" major: %u\n", tag_smbios->major);
printf(" minor: %u\n", tag_smbios->minor);
KERNAUX_CAST_CONST(unsigned long, major, tag_smbios->major);
KERNAUX_CAST_CONST(unsigned long, minor, tag_smbios->minor);
KERNAUX_CAST_CONST(unsigned long, reserved0, tag_smbios->reserved1[0]);
KERNAUX_CAST_CONST(unsigned long, reserved1, tag_smbios->reserved1[1]);
KERNAUX_CAST_CONST(unsigned long, reserved2, tag_smbios->reserved1[2]);
KERNAUX_CAST_CONST(unsigned long, reserved3, tag_smbios->reserved1[3]);
KERNAUX_CAST_CONST(unsigned long, reserved4, tag_smbios->reserved1[4]);
KERNAUX_CAST_CONST(unsigned long, reserved5, tag_smbios->reserved1[5]);
printf(
" reserved1: {%u, %u, %u, %u, %u, %u}\n",
tag_smbios->reserved1[0],
tag_smbios->reserved1[1],
tag_smbios->reserved1[2],
tag_smbios->reserved1[3],
tag_smbios->reserved1[4],
tag_smbios->reserved1[5]
PRINTLNF(" major: %lu", major);
PRINTLNF(" minor: %lu", minor);
PRINTLNF(
" reserved1: {%lu, %lu, %lu, %lu, %lu, %lu}",
reserved0, reserved1, reserved2,
reserved3, reserved4, reserved5
);
}
break;
@ -213,61 +262,67 @@ void KernAux_Multiboot2_ITagBase_print(
}
break;
case KERNAUX_MULTIBOOT2_ITAG_IMAGE_LOAD_BASE_PHYS_ADDR:
printf(
" load base addr: %u\n",
((struct KernAux_Multiboot2_ITag_ImageLoadBasePhysAddr*)tag_base)->
load_base_addr
);
{
KERNAUX_CAST_CONST(
unsigned long,
load_base_addr,
((struct KernAux_Multiboot2_ITag_ImageLoadBasePhysAddr*)
tag_base)->load_base_addr
);
PRINTLNF(" load base addr: %lu", load_base_addr);
}
break;
}
}
void KernAux_Multiboot2_ITag_BootCmdLine_print(
const struct KernAux_Multiboot2_ITag_BootCmdLine *const tag,
void (*printf)(const char *format, ...)
const KernAux_Display display
) {
KERNAUX_ASSERT(tag);
KERNAUX_ASSERT(printf);
KERNAUX_ASSERT(display);
if (!KernAux_Multiboot2_ITag_BootCmdLine_is_valid(tag)) {
printf(" invalid!\n");
PRINTLN(" invalid!");
return;
}
printf(" cmdline: %s\n", KERNAUX_MULTIBOOT2_DATA(tag));
PRINTLNF(" cmdline: %s", KERNAUX_MULTIBOOT2_DATA(tag));
}
void KernAux_Multiboot2_ITag_BootLoaderName_print(
const struct KernAux_Multiboot2_ITag_BootLoaderName *const tag,
void (*printf)(const char *format, ...)
const KernAux_Display display
) {
KERNAUX_ASSERT(tag);
KERNAUX_ASSERT(printf);
KERNAUX_ASSERT(display);
if (!KernAux_Multiboot2_ITag_BootLoaderName_is_valid(tag)) {
printf(" invalid!\n");
PRINTLN(" invalid!");
return;
}
printf(" name: %s\n", KERNAUX_MULTIBOOT2_DATA(tag));
PRINTLNF(" name: %s", KERNAUX_MULTIBOOT2_DATA(tag));
}
void KernAux_Multiboot2_ITag_MemoryMap_print(
const struct KernAux_Multiboot2_ITag_MemoryMap *const tag,
void (*printf)(const char *format, ...)
const KernAux_Display display
) {
KERNAUX_ASSERT(tag);
KERNAUX_ASSERT(printf);
KERNAUX_ASSERT(display);
if (!KernAux_Multiboot2_ITag_MemoryMap_is_valid(tag)) {
printf(" invalid!\n");
PRINTLN(" invalid!");
return;
}
printf(" entry size: %u\n", tag->entry_size);
printf(" entry version: %u\n", tag->entry_version);
KERNAUX_CAST_CONST(unsigned long, entry_size, tag->entry_size);
KERNAUX_CAST_CONST(unsigned long, entry_version, tag->entry_version);
printf(" entries:\n");
PRINTLNF(" entry size: %lu", entry_size);
PRINTLNF(" entry version: %lu", entry_version);
PRINTLN(" entries:");
const struct KernAux_Multiboot2_ITag_MemoryMap_EntryBase *const entries =
(struct KernAux_Multiboot2_ITag_MemoryMap_EntryBase*)
@ -278,30 +333,40 @@ void KernAux_Multiboot2_ITag_MemoryMap_print(
index < (tag->base.size - sizeof(*tag)) / tag->entry_size;
++index
) {
printf(" entry %lu\n", index);
printf(" base addr: %llu\n", entries[index].base_addr);
printf(" length: %llu\n", entries[index].length);
printf(" type: %u\n", entries[index].type);
printf(" reserved1: %u\n", entries[index].reserved1);
KERNAUX_CAST_CONST(unsigned long long, base_addr, entries[index].base_addr);
KERNAUX_CAST_CONST(unsigned long long, length, entries[index].length);
KERNAUX_CAST_CONST(unsigned long, type, entries[index].type);
KERNAUX_CAST_CONST(unsigned long, reserved1, entries[index].reserved1);
PRINTLNF(" entry %zu", index);
PRINTLNF(" base addr: %llu", base_addr);
PRINTLNF(" length: %llu", length);
PRINTLNF(" type: %lu", type);
PRINTLNF(" reserved1: %lu", reserved1);
}
}
void KernAux_Multiboot2_ITag_ELFSymbols_print(
const struct KernAux_Multiboot2_ITag_ELFSymbols *const tag,
void (*printf)(const char *format, ...)
const KernAux_Display display
) {
KERNAUX_ASSERT(tag);
KERNAUX_ASSERT(printf);
KERNAUX_ASSERT(display);
if (!KernAux_Multiboot2_ITag_ELFSymbols_is_valid(tag)) {
printf(" invalid!\n");
PRINTLN(" invalid!");
return;
}
printf(" num: %hu\n", tag->num);
printf(" entsize: %hu\n", tag->ent_size);
printf(" shndx: %hu\n", tag->shndx);
printf(" reserved1: %hu\n", tag->reserved1);
KERNAUX_CAST_CONST(unsigned long, num, tag->num);
KERNAUX_CAST_CONST(unsigned long, ent_size, tag->ent_size);
KERNAUX_CAST_CONST(unsigned long, shndx, tag->shndx);
KERNAUX_CAST_CONST(unsigned long, reserved1, tag->reserved1);
PRINTLNF(" num: %lu", num);
PRINTLNF(" entsize: %lu", ent_size);
PRINTLNF(" shndx: %lu", shndx);
PRINTLNF(" reserved1: %lu", reserved1);
// TODO: implement this
}

View File

@ -2,6 +2,10 @@
#include "config.h"
#endif
#define KERNAUX_ACCESS_PROTECTED
#include <kernaux/generic/display.h>
#include <kernaux/macro.h>
#include <kernaux/multiboot2.h>
#include <assert.h>
@ -10,14 +14,22 @@
#include "multiboot2_header_example1.h"
static void my_printf(const char *format, ...)
static void my_putc(void *display KERNAUX_UNUSED, char c)
{
va_list va;
va_start(va, format);
vprintf(format, va);
va_end(va);
putchar(c);
}
static
void my_vprintf(void *display KERNAUX_UNUSED, const char *format, va_list va)
{
vprintf(format, va);
}
static const struct KernAux_Display display = {
.putc = my_putc,
.vprintf = my_vprintf,
};
void test_main()
{
assert(KernAux_Multiboot2_Header_is_valid(
@ -26,6 +38,6 @@ void test_main()
KernAux_Multiboot2_Header_print(
(struct KernAux_Multiboot2_Header*)&multiboot2_header_example1,
my_printf
&display
);
}

View File

@ -2,6 +2,10 @@
#include "config.h"
#endif
#define KERNAUX_ACCESS_PROTECTED
#include <kernaux/generic/display.h>
#include <kernaux/macro.h>
#include <kernaux/multiboot2.h>
#include <assert.h>
@ -10,14 +14,22 @@
#include "multiboot2_header_example2.h"
static void my_printf(const char *format, ...)
static void my_putc(void *display KERNAUX_UNUSED, char c)
{
va_list va;
va_start(va, format);
vprintf(format, va);
va_end(va);
putchar(c);
}
static
void my_vprintf(void *display KERNAUX_UNUSED, const char *format, va_list va)
{
vprintf(format, va);
}
static const struct KernAux_Display display = {
.putc = my_putc,
.vprintf = my_vprintf,
};
void test_main()
{
assert(KernAux_Multiboot2_Header_is_valid(
@ -26,6 +38,6 @@ void test_main()
KernAux_Multiboot2_Header_print(
&multiboot2_header_example2.multiboot2_header,
my_printf
&display
);
}

View File

@ -2,6 +2,10 @@
#include "config.h"
#endif
#define KERNAUX_ACCESS_PROTECTED
#include <kernaux/generic/display.h>
#include <kernaux/macro.h>
#include <kernaux/multiboot2.h>
#include <assert.h>
@ -10,14 +14,22 @@
#include "multiboot2_info_example1.h"
static void my_printf(const char *format, ...)
static void my_putc(void *display KERNAUX_UNUSED, char c)
{
va_list va;
va_start(va, format);
vprintf(format, va);
va_end(va);
putchar(c);
}
static
void my_vprintf(void *display KERNAUX_UNUSED, const char *format, va_list va)
{
vprintf(format, va);
}
static const struct KernAux_Display display = {
.putc = my_putc,
.vprintf = my_vprintf,
};
void test_main()
{
assert(KernAux_Multiboot2_Info_is_valid(
@ -26,6 +38,6 @@ void test_main()
KernAux_Multiboot2_Info_print(
(struct KernAux_Multiboot2_Info*)multiboot2_info_example1,
my_printf
&display
);
}

View File

@ -2,6 +2,10 @@
#include "config.h"
#endif
#define KERNAUX_ACCESS_PROTECTED
#include <kernaux/generic/display.h>
#include <kernaux/macro.h>
#include <kernaux/multiboot2.h>
#include <assert.h>
@ -10,14 +14,22 @@
#include "multiboot2_info_example2.h"
static void my_printf(const char *format, ...)
static void my_putc(void *display KERNAUX_UNUSED, char c)
{
va_list va;
va_start(va, format);
vprintf(format, va);
va_end(va);
putchar(c);
}
static
void my_vprintf(void *display KERNAUX_UNUSED, const char *format, va_list va)
{
vprintf(format, va);
}
static const struct KernAux_Display display = {
.putc = my_putc,
.vprintf = my_vprintf,
};
void test_main()
{
assert(KernAux_Multiboot2_Info_is_valid(
@ -26,6 +38,6 @@ void test_main()
KernAux_Multiboot2_Info_print(
&multiboot2_info_example2.multiboot2_info,
my_printf
&display
);
}

View File

@ -7,27 +7,126 @@
#include <assert.h>
#include <string.h>
static void test_idte_set_offset();
static void test_idte_init_intr();
static void test_idte_init_task();
static void test_idte_init_trap();
static void test_idte_get_and_set_offset();
static void test_idte_get_dpl();
void test_main()
{
test_idte_set_offset();
test_idte_init_intr();
test_idte_init_task();
test_idte_init_trap();
test_idte_get_and_set_offset();
test_idte_get_dpl();
}
void test_idte_set_offset()
void test_idte_init_intr()
{
struct KernAux_Arch_I386_IDTE idte;
memset(&idte, 0xff, sizeof(idte));
KernAux_Arch_I386_IDTE_init_intr(&idte, 0x12345678, 0xcafe, 0);
assert(KernAux_Arch_I386_IDTE_offset(&idte) == 0x12345678);
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 0);
assert(idte.selector == 0xcafe);
assert(idte._ == 0);
assert(idte.flags == 0x8e); // 1-00-01110
KernAux_Arch_I386_IDTE_init_intr(&idte, 0x12345678, 0xcafe, 3);
assert(KernAux_Arch_I386_IDTE_offset(&idte) == 0x12345678);
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 3);
assert(idte.selector == 0xcafe);
assert(idte._ == 0);
assert(idte.flags == 0xee); // 1-11-01110
}
void test_idte_init_task()
{
struct KernAux_Arch_I386_IDTE idte;
memset(&idte, 0xff, sizeof(idte));
KernAux_Arch_I386_IDTE_init_task(&idte, 0xcafe, 0);
assert(KernAux_Arch_I386_IDTE_offset(&idte) == 0);
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 0);
assert(idte.selector == 0xcafe);
assert(idte._ == 0);
assert(idte.flags == 0x85); // 1-00-00101
KernAux_Arch_I386_IDTE_init_task(&idte, 0xcafe, 3);
assert(KernAux_Arch_I386_IDTE_offset(&idte) == 0);
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 3);
assert(idte.selector == 0xcafe);
assert(idte._ == 0);
assert(idte.flags == 0xe5); // 1-11-00101
}
void test_idte_init_trap()
{
struct KernAux_Arch_I386_IDTE idte;
memset(&idte, 0xff, sizeof(idte));
KernAux_Arch_I386_IDTE_init_trap(&idte, 0x12345678, 0xcafe, 0);
assert(KernAux_Arch_I386_IDTE_offset(&idte) == 0x12345678);
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 0);
assert(idte.selector == 0xcafe);
assert(idte._ == 0);
assert(idte.flags == 0x8f); // 1-00-01111
KernAux_Arch_I386_IDTE_init_trap(&idte, 0x12345678, 0xcafe, 3);
assert(KernAux_Arch_I386_IDTE_offset(&idte) == 0x12345678);
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 3);
assert(idte.selector == 0xcafe);
assert(idte._ == 0);
assert(idte.flags == 0xef); // 1-11-01111
}
void test_idte_get_and_set_offset()
{
struct KernAux_Arch_I386_IDTE idte;
memset(&idte, 0xff, sizeof(idte));
KernAux_Arch_I386_IDTE_set_offset(&idte, 0);
assert(idte.offset_high == 0);
assert(idte.offset_low == 0);
assert(KernAux_Arch_I386_IDTE_offset(&idte) == 0);
memset(&idte, 0, sizeof(idte));
KernAux_Arch_I386_IDTE_set_offset(&idte, 0xffffffff);
assert(idte.offset_high == 0xffff);
assert(idte.offset_low == 0xffff);
assert(KernAux_Arch_I386_IDTE_offset(&idte) == 0xffffffff);
memset(&idte, 0, sizeof(idte));
KernAux_Arch_I386_IDTE_set_offset(&idte, 0x12345678);
assert(idte.offset_high == 0x1234);
assert(idte.offset_low == 0x5678);
assert(KernAux_Arch_I386_IDTE_offset(&idte) == 0x12345678);
}
void test_idte_get_dpl()
{
struct KernAux_Arch_I386_IDTE idte;
memset(&idte, 0, sizeof(idte));
KernAux_Arch_I386_IDTE_set_offset(&idte, 0);
assert(idte.offset_high == 0);
assert(idte.offset_low == 0);
idte.flags = 0; // 0-00-00000
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 0);
idte.flags = 0x80; // 1-00-00000
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 0);
KernAux_Arch_I386_IDTE_set_offset(&idte, 0xFFFFFFFF);
assert(idte.offset_high == 0xFFFF);
assert(idte.offset_low == 0xFFFF);
idte.flags = 0x20; // 0-01-00000
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 1);
idte.flags = 0xa0; // 1-01-00000
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 1);
KernAux_Arch_I386_IDTE_set_offset(&idte, 0x12345678);
assert(idte.offset_high == 0x1234);
assert(idte.offset_low == 0x5678);
idte.flags = 0x40; // 0-10-00000
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 2);
idte.flags = 0xc0; // 1-10-00000
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 2);
idte.flags = 0x60; // 0-11-00000
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 3);
idte.flags = 0xe0; // 1-11-00000
assert(KernAux_Arch_I386_IDTE_dpl(&idte) == 3);
}