Luna/kernel/src/init/InitRD.cpp

97 lines
2.4 KiB
C++
Raw Normal View History

2022-09-14 15:55:24 +00:00
#define MODULE "initrd"
2022-09-05 14:13:51 +00:00
#include "init/InitRD.h"
#include "bootboot.h"
#include "io/Serial.h"
2022-09-14 15:55:24 +00:00
#include "log/Log.h"
2022-09-10 20:15:19 +00:00
#include "memory/KernelMemoryManager.h"
2022-09-05 14:13:51 +00:00
#include "std/stdlib.h"
#include <string.h>
extern BOOTBOOT bootboot;
2022-09-19 15:06:08 +00:00
static void* initrd_base;
2022-09-05 14:13:51 +00:00
static inline int get_file_size_in_blocks(InitRD::File f)
{
return f.size_in_blocks;
}
inline int InitRD::get_total_blocks()
{
return bootboot.initrd_size / TAR_BLOCKSIZE;
}
inline InitRD::TarHeader* InitRD::get_block(int block_index)
{
2022-09-19 15:06:08 +00:00
return (TarHeader*)((uintptr_t)initrd_base + block_index * TAR_BLOCKSIZE);
2022-09-05 14:13:51 +00:00
}
inline bool InitRD::is_valid_header(TarHeader* header)
{
return strncmp(header->magic, TAR_MAGIC, 5) == 0;
}
InitRD::File InitRD::get_file(TarHeader* header)
{
File result;
result.size = 0;
memcpy(result.name, header->name, 100);
int multiplier =
1; // why they decided to store the size as an octal-encoded string instead of an integer is beyond me
for (int i = 10; i >= 0; i--)
{
result.size += (multiplier * (header->size[i] - 48));
multiplier *= 8;
}
2022-09-19 15:06:08 +00:00
result.addr = (void*)((uint64_t)header + TAR_BLOCKSIZE);
result.size_in_blocks = (result.size + (TAR_BLOCKSIZE - 1)) / TAR_BLOCKSIZE;
2022-09-05 14:13:51 +00:00
return result;
}
2022-09-10 20:15:19 +00:00
InitRD::File InitRD::open(const char* filename)
2022-09-05 14:13:51 +00:00
{
int block = 0;
int total_blocks = get_total_blocks();
while (block < total_blocks)
{
2022-09-19 15:06:08 +00:00
TarHeader* hdr = (TarHeader*)get_block(block);
2022-09-14 15:55:24 +00:00
if (hdr->typeflag == 53 || !is_valid_header(hdr))
{
block++;
continue;
}
2022-09-05 14:13:51 +00:00
auto f = get_file(hdr);
if (strncmp(hdr->name, filename, strlen(filename)) == 0) { return f; }
2022-09-14 15:55:24 +00:00
block += get_file_size_in_blocks(f) + 1;
2022-09-05 14:13:51 +00:00
}
File nullFile;
nullFile.addr = NULL;
nullFile.size = 0;
memcpy(nullFile.name, "NULL", 5);
return nullFile;
}
void InitRD::for_each(void (*callback)(File& f))
{
int block = 0;
int total_blocks = get_total_blocks();
while (block < total_blocks)
{
2022-09-19 15:06:08 +00:00
TarHeader* hdr = (TarHeader*)get_block(block);
2022-09-14 15:55:24 +00:00
if (hdr->typeflag == 53 || !is_valid_header(hdr))
2022-09-11 06:23:32 +00:00
{
2022-09-14 15:55:24 +00:00
block++;
2022-09-11 06:23:32 +00:00
continue;
}
2022-09-05 14:13:51 +00:00
auto f = get_file(hdr);
2022-09-14 15:55:24 +00:00
block += get_file_size_in_blocks(f) + 1;
2022-09-05 14:13:51 +00:00
callback(f);
}
2022-09-19 15:06:08 +00:00
}
void InitRD::init()
{
initrd_base =
KernelMemoryManager::get_unaligned_mappings((void*)bootboot.initrd_ptr, bootboot.initrd_size / 4096 + 1);
2022-09-05 14:13:51 +00:00
}