kernel/src/info.c

307 lines
9.1 KiB
C
Raw Normal View History

2017-11-09 16:00:36 +00:00
#include "info.h"
#include "panic.h"
2021-12-17 23:30:09 +00:00
#include <kernaux/assert.h>
2022-06-23 10:51:42 +00:00
#include <kernaux/drivers/console.h>
2022-06-24 05:50:07 +00:00
#include <string.h>
2021-12-17 22:35:04 +00:00
2021-12-17 22:32:04 +00:00
static bool cmdline_terminated(const char *s);
2017-11-04 14:03:45 +00:00
2021-12-19 00:20:14 +00:00
/******************
* Initialization *
******************/
2021-12-17 23:26:56 +00:00
void kernel_info_init_start(
2021-12-17 22:45:22 +00:00
struct Kernel_Info *const kinfo,
const size_t offset,
const size_t size,
const size_t phys_base,
const size_t virt_base,
2021-12-18 21:59:16 +00:00
const size_t stack_start,
const size_t stack_size
2021-12-17 22:45:22 +00:00
) {
2022-06-23 10:46:21 +00:00
KERNAUX_ASSERT(kinfo);
2021-12-17 23:30:09 +00:00
2021-12-17 22:35:04 +00:00
memset(kinfo, 0, sizeof(*kinfo));
2021-12-17 22:45:22 +00:00
2021-12-19 00:11:12 +00:00
kinfo->initialized = false;
2021-12-17 22:45:22 +00:00
kinfo->kernel_offset = offset;
kinfo->kernel_size = size;
kinfo->kernel_phys_base = phys_base;
kinfo->kernel_virt_base = virt_base;
2021-12-18 21:59:16 +00:00
kinfo->kernel_stack_start = stack_start;
kinfo->kernel_stack_size = stack_size;
2021-12-17 22:35:04 +00:00
}
2021-12-18 02:42:03 +00:00
void kernel_info_init_finish(struct Kernel_Info *const kinfo)
{
2022-06-23 10:46:21 +00:00
KERNAUX_ASSERT(kinfo);
KERNAUX_ASSERT(!kinfo->initialized);
2021-12-18 02:42:03 +00:00
kinfo->kernel_and_modules_total_size =
kinfo->kernel_size + kinfo->modules_total_size;
2021-12-19 00:11:12 +00:00
kinfo->initialized = true;
2021-12-18 02:42:03 +00:00
}
2021-12-19 00:20:14 +00:00
void kernel_info_init_from_multiboot2(
struct Kernel_Info *kinfo,
2022-01-13 04:27:01 +00:00
const struct KernAux_Multiboot2_Info *multiboot2_info
2021-12-19 00:20:14 +00:00
) {
2022-06-23 10:46:21 +00:00
KERNAUX_ASSERT(kinfo);
KERNAUX_ASSERT(multiboot2_info);
KERNAUX_ASSERT(!kinfo->initialized);
2021-12-19 00:20:14 +00:00
{
const char *const cmdline =
2022-01-13 04:27:01 +00:00
KernAux_Multiboot2_Info_boot_cmd_line(multiboot2_info);
2021-12-19 00:20:14 +00:00
if (cmdline) {
assert(strlen(cmdline) <= KERNEL_INFO_CMDLINE_SLEN_MAX,
"Kernel cmdline is too long");
strcpy(kinfo->cmdline, cmdline);
} else {
memset(kinfo->cmdline, '\0', sizeof(kinfo->cmdline));
}
}
{
2022-01-13 04:27:01 +00:00
const struct KernAux_Multiboot2_ITag_MemoryMap *const tag =
(struct KernAux_Multiboot2_ITag_MemoryMap*)
KernAux_Multiboot2_Info_first_tag_with_type(
2021-12-19 00:20:14 +00:00
multiboot2_info,
2022-01-13 04:27:01 +00:00
KERNAUX_MULTIBOOT2_ITAG_MEMORY_MAP
2021-12-19 00:20:14 +00:00
);
if (!tag) {
panic("No memory map provided in Multiboot 2 info.");
}
for (
2022-01-13 04:27:01 +00:00
const struct KernAux_Multiboot2_ITag_MemoryMap_EntryBase *entry =
(struct KernAux_Multiboot2_ITag_MemoryMap_EntryBase*)
2022-01-11 10:32:47 +00:00
KERNAUX_MULTIBOOT2_DATA(tag);
2021-12-19 00:20:14 +00:00
(unsigned char*)entry < (unsigned char*)tag + tag->base.size;
entry =
2022-01-13 04:27:01 +00:00
(struct KernAux_Multiboot2_ITag_MemoryMap_EntryBase*)
2021-12-19 00:20:14 +00:00
((unsigned char*)entry + tag->entry_size)
) {
if (kinfo->areas_count >= KERNEL_INFO_AREAS_MAX) {
panic("Too many memory map entries in Multiboot 2 info.");
}
struct Kernel_Info_Area *const area =
&kinfo->areas[kinfo->areas_count];
area->base = entry->base_addr;
area->size = entry->length;
area->limit = area->base + area->size - 1;
area->is_available = entry->type == 1;
++kinfo->areas_count;
}
}
for (
2022-01-13 04:27:01 +00:00
const struct KernAux_Multiboot2_ITag_Module *tag =
(struct KernAux_Multiboot2_ITag_Module*)
KernAux_Multiboot2_Info_first_tag_with_type(
2021-12-19 00:20:14 +00:00
multiboot2_info,
2022-01-13 04:27:01 +00:00
KERNAUX_MULTIBOOT2_ITAG_MODULE
2021-12-19 00:20:14 +00:00
);
tag;
2022-01-13 04:27:01 +00:00
tag = (struct KernAux_Multiboot2_ITag_Module*)
KernAux_Multiboot2_Info_tag_with_type_after(
2021-12-19 00:20:14 +00:00
multiboot2_info,
2022-01-13 04:27:01 +00:00
KERNAUX_MULTIBOOT2_ITAG_MODULE,
(struct KernAux_Multiboot2_ITagBase*)tag
2021-12-19 00:20:14 +00:00
)
) {
if (kinfo->modules_count >= KERNEL_INFO_MODULES_MAX) {
panic("Too many modules in Multiboot 2 info.");
}
2022-01-11 10:32:47 +00:00
unsigned int slen = strlen((char*)KERNAUX_MULTIBOOT2_DATA(tag));
2021-12-19 00:20:14 +00:00
if (slen > KERNEL_INFO_CMDLINE_SLEN_MAX) {
panic("Multiboot 2 module cmd line is too long.");
}
struct Kernel_Info_Module *const module =
&kinfo->modules[kinfo->modules_count];
2022-01-11 10:32:47 +00:00
strcpy(module->cmdline, (char*)KERNAUX_MULTIBOOT2_DATA(tag));
2021-12-19 00:20:14 +00:00
module->base = tag->mod_start;
module->limit = tag->mod_end;
module->size = module->limit - module->base + 1;
++kinfo->modules_count;
kinfo->modules_total_size += module->size;
}
}
/*******************************
* Other kernel info functions *
*******************************/
2021-12-17 23:05:01 +00:00
void kernel_info_print(const struct Kernel_Info *const kinfo)
{
2022-06-23 10:46:21 +00:00
KERNAUX_ASSERT(kinfo);
2021-12-17 23:30:09 +00:00
2022-06-23 10:51:42 +00:00
kernaux_drivers_console_printf("Kernel info\n");
kernaux_drivers_console_printf(" cmdline: %s\n", kinfo->cmdline);
kernaux_drivers_console_printf(" modules: %lu\n", kinfo->modules_count);
kernaux_drivers_console_printf(" areas: %lu\n", kinfo->areas_count);
kernaux_drivers_console_printf("\n");
kernaux_drivers_console_printf(" offset: %lu\n", kinfo->kernel_offset);
kernaux_drivers_console_printf(" size: %lu\n", kinfo->kernel_size);
kernaux_drivers_console_printf(" phys base: %lu\n", kinfo->kernel_phys_base);
kernaux_drivers_console_printf(" virt base: %lu\n", kinfo->kernel_virt_base);
kernaux_drivers_console_printf("\n");
kernaux_drivers_console_printf(" modules size: %lu\n", kinfo->modules_total_size);
kernaux_drivers_console_printf(" kernel & modules size: %lu\n", kinfo->kernel_and_modules_total_size);
kernaux_drivers_console_printf("\n");
kernaux_drivers_console_printf(" stack start: %lu\n", kinfo->kernel_stack_start);
kernaux_drivers_console_printf(" stack size: %lu\n", kinfo->kernel_stack_size);
2021-12-17 23:05:01 +00:00
}
2021-12-18 02:42:03 +00:00
bool kernel_info_is_valid(const struct Kernel_Info *const kinfo)
2020-11-26 18:50:25 +00:00
{
2022-06-23 10:46:21 +00:00
KERNAUX_ASSERT(kinfo);
KERNAUX_ASSERT(kinfo->initialized);
2017-11-04 14:03:45 +00:00
2021-12-17 22:32:04 +00:00
if (!cmdline_terminated(kinfo->cmdline)) return false;
2017-11-04 14:03:45 +00:00
2021-12-17 22:32:04 +00:00
if (kinfo->modules_count > KERNEL_INFO_MODULES_MAX) return false;
if (kinfo->areas_count > KERNEL_INFO_AREAS_MAX) return false;
2017-11-04 14:03:45 +00:00
2021-12-17 22:32:04 +00:00
if (kinfo->kernel_offset == 0) return false;
if (kinfo->kernel_size == 0) return false;
2017-11-04 14:03:45 +00:00
2021-12-17 22:32:04 +00:00
if (kinfo->kernel_virt_base - kinfo->kernel_phys_base !=
kinfo->kernel_offset)
{
return false;
2017-11-04 14:03:45 +00:00
}
2021-12-18 21:59:16 +00:00
if (kinfo->kernel_stack_size != 16 * 1024) return false;
if (!(kinfo->kernel_stack_start >= kinfo->kernel_phys_base &&
kinfo->kernel_stack_start <
kinfo->kernel_phys_base + kinfo->kernel_size))
{
return false;
}
const size_t stack_end =
kinfo->kernel_stack_start + kinfo->kernel_stack_size;
if (!(stack_end - 1 >= kinfo->kernel_phys_base &&
stack_end - 1 < kinfo->kernel_phys_base + kinfo->kernel_size))
{
return false;
}
2021-12-17 22:32:04 +00:00
size_t modules_total_size = 0;
2017-11-04 14:03:45 +00:00
2021-12-17 22:32:04 +00:00
for (size_t i = 0; i < kinfo->modules_count; ++i) {
2021-12-12 14:00:17 +00:00
const struct Kernel_Info_Module *const module = &kinfo->modules[i];
2017-11-04 14:03:45 +00:00
modules_total_size += module->size;
2021-12-17 22:32:04 +00:00
if (module->size == 0) return false;
if (module->base + module->size != module->limit + 1) return false;
if (!cmdline_terminated(module->cmdline)) return false;
2017-11-04 14:03:45 +00:00
}
2021-12-17 22:32:04 +00:00
if (kinfo->modules_total_size != modules_total_size) return false;
2017-11-04 14:03:45 +00:00
2021-12-17 22:32:04 +00:00
if (kinfo->kernel_and_modules_total_size !=
kinfo->kernel_size + kinfo->modules_total_size)
{
return false;
2017-11-04 14:03:45 +00:00
}
2021-12-17 22:32:04 +00:00
uint64_t last = 0;
2017-11-04 14:03:45 +00:00
2021-12-17 22:32:04 +00:00
for (size_t i = 0; i < kinfo->areas_count; ++i) {
2021-12-12 14:00:17 +00:00
const struct Kernel_Info_Area *const area = &kinfo->areas[i];
2017-11-04 14:03:45 +00:00
2021-12-17 22:32:04 +00:00
if (last > area->base) return false;
if (area->size == 0) return false;
if (area->base + area->size != area->limit + 1) return false;
2017-11-04 14:03:45 +00:00
last = area->limit + 1;
if (!area->is_available) {
2020-11-26 18:50:25 +00:00
if (kinfo->kernel_phys_base >= area->base &&
2021-12-17 22:32:04 +00:00
kinfo->kernel_phys_base <= area->limit)
{
return false;
2017-11-04 14:03:45 +00:00
}
2021-12-18 21:37:05 +00:00
if (kinfo->kernel_phys_base + kinfo->kernel_size - 1 >= area->base
&&
kinfo->kernel_phys_base + kinfo->kernel_size - 1 <= area->limit)
2021-12-17 22:32:04 +00:00
{
return false;
2017-11-04 14:03:45 +00:00
}
2020-11-26 18:50:25 +00:00
for (unsigned int j = 0; j < kinfo->modules_count; ++j) {
2021-12-17 22:32:04 +00:00
const struct Kernel_Info_Module *const module =
&kinfo->modules[j];
2017-11-04 14:03:45 +00:00
2021-12-17 22:32:04 +00:00
if (module->base >= area->base && module->base <= area->limit) {
return false;
2017-11-04 14:03:45 +00:00
}
if (module->limit >= area->base &&
2021-12-17 22:32:04 +00:00
module->limit <= area->limit)
{
return false;
2017-11-04 14:03:45 +00:00
}
}
}
}
2021-12-18 02:42:03 +00:00
return true;
2021-12-18 02:29:25 +00:00
}
2021-12-19 00:39:04 +00:00
void kernel_info_setup_pfa(
const struct Kernel_Info *const kinfo,
const KernAux_PFA pfa
) {
2022-06-23 10:46:21 +00:00
KERNAUX_ASSERT(kinfo);
KERNAUX_ASSERT(pfa);
KERNAUX_ASSERT(kinfo->initialized);
2021-12-19 00:39:04 +00:00
for (size_t i = 0; i < kinfo->areas_count; ++i) {
const struct Kernel_Info_Area *const area = &kinfo->areas[i];
if (area->is_available) {
KernAux_PFA_mark_available(pfa, area->base, area->limit);
}
}
}
/*********************
* Utility functions *
*********************/
2021-12-17 22:32:04 +00:00
bool cmdline_terminated(const char *const str)
2017-11-04 14:03:45 +00:00
{
2021-12-17 22:32:04 +00:00
for (size_t i = 0; i < KERNEL_INFO_CMDLINE_SIZE_MAX; ++i) {
if (str[i] == '\0') return true;
2017-11-04 14:03:45 +00:00
}
2021-12-17 22:32:04 +00:00
return false;
2017-11-04 14:03:45 +00:00
}