Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
initrd.c
Go to the documentation of this file.
1#include "initrd.h"
2#include "hal/cpu/paging.h"
3#include "init/init.h"
4#include "libk/oct2bin.h"
5#include <spinlock.h>
6#include <vector.h>
7
8#include "type.h"
9#include "vfs/cache.h"
10#include "vfs/dentry.h"
11#include "vfs/enum.h"
12#include "vfs/filesystem.h"
13#include <vfs/vfs.h>
14#include <vfs/vnode.h>
15
16#include <libk/fs/tar.h>
17#include <libk/serial.h>
18#include <str.h>
19
20#include <memory/kalloc.h>
21#include <memory/memory_utils.h>
23#include <memory/slab.h>
24#include <memory/vm_manager.h>
25#include <autoconf.h>
26
27
34
39
40// local use
42
45
46INIT(initrd) {
47 initrd_module_t* initrd_module = &ctx->initrd_module;
49 uint64_t paddr_alligned = (uint64_t)(paddr & ~(BLOCK_SIZE - 1));
50 uint64_t offset = paddr - paddr_alligned;
51 uint64_t page_count =
53
54 vxMultipleMmap(paging_get_highest_page_map(), 0xFFFFE00000000000,
55 paddr_alligned, page_count, 0b111);
57 __initrd_data.virt_addr = 0xFFFFE00000000000 + offset;
58
59 LOG_INFO("INITRD", "paddr 0x%x aligned to 0x%x off 0x%x", paddr, paddr,
60 paddr_alligned - paddr);
61
62 LOG_INFO("INITRD",
63 "initrd module found at 0x%x (size %d kb), alligned to %d kb",
64 __initrd_data.virt_addr, initrd_module->size / 1024,
65 page_count * BLOCK_SIZE / 1024);
66
69
70 /* We dont need to create a cdev cause initrd already on memory
71 create init directory */
72 dentry_ptr init_dentry = 0;
73 {
74 vxnamei(VOXIA_INITRD_MOUNT_PATH, &init_dentry);
75 auto inode = create_and_attach_vnode();
76 init_dentry->vnode = inode;
77 inode->permission = 660;
78 inode->type = VNODE_TYPE_DIR;
79
80 LOG_DEBUG("INITRD", "entry name %s", init_dentry->name->c_str);
81 }
82
83 LoadIntoVfs(init_dentry);
84
85 LOG_INFO("INITRD", "initrd registered");
86}
87
88static int initrd_read(vnode_t* vnode, void* buf, size_t len, size_t offset) {
90 if (!data)
91 return 0;
92
93 auto off = data->offset;
94 uint8_t* addr = (uint8_t*)__initrd_data.virt_addr + off + offset;
95 memcopy(buf, addr, len);
96 return 1;
97}
98
100 uint8_t* const base = (uint8_t*)__initrd_data.virt_addr;
101 uint64_t offset = 0;
102
103 vops_file_t* initrd_file_ops =
104 (vops_file_t*)kalloc(sizeof(vops_file_t));
105 initrd_file_ops->read = initrd_read;
106
107 LOG_DEBUG("INITRD", "loading initrd into vfs started from %s",
108 dentry->name->c_str);
109
110 while (1) {
111 if (offset + sizeof(TarHeader) > __initrd_data.size)
112 break;
113
114 TarHeader header;
115 memcopy(&header, base + offset, sizeof(TarHeader));
116
117 if (strncmp(header.ustar, "ustar", 5) != 0)
118 break;
119
120 size_t size = (size_t)oct2bin((unsigned char*)header.size,
121 sizeof(header.size));
122
123 if (size > __initrd_data.size - offset - sizeof(TarHeader)) {
124 LOG_ERROR("INITRD",
125 "invalid entry size %zu at offset %llu, "
126 "aborting",
127 size, (unsigned long long)offset);
128 break;
129 }
130
131 LOG2_INFO("INITRD", "registering file %s", header.filename);
132
133 uint64_t data_size_aligned =
134 ((uint64_t)size + 511u) & ~(uint64_t)511u;
135 uint64_t next_offset = offset + 512u + data_size_aligned;
136
137 if (next_offset < offset) { /* wraparound */
138 LOG_ERROR("INITRD", "offset overflow at %llu, aborting",
139 (unsigned long long)offset);
140 break;
141 }
142
143 {
144 dentry_ptr last_dentry = NULL;
145 if (resolve_dentry(header.filename, dentry,
146 &last_dentry,
148 LOG_ERROR("VFS", "failed create dentry for %s",
149 header.filename);
150 }
151
152 if (last_dentry) {
154 last_dentry->vnode = vnode;
155 vnode->permission = (uint16_t)oct2bin(
156 (unsigned char*)header.mode,
157 sizeof(header.mode));
158
159 vnode->size = size;
160 switch (header.typeflag) {
161 case '5':
163 break;
164 case '0': {
166 vnode->ops = initrd_file_ops;
168 data = (struct
170 kalloc(sizeof(
171 struct
173 data->offset = offset + 512u;
174 vnode->vnode_private = (void*)data;
175 break;
176 }
177 default:
178 LOG_WARN("INITRD",
179 "unhandled typeflag '%c' for "
180 "%s",
181 header.typeflag,
182 header.filename);
183 break;
184 }
185 }
186 }
187
188 offset = next_offset;
189 }
190
191 LOG_DEBUG("INITRD", "done loading initrd into vfs");
193}
struct SDT header
Definition acpi.h:0
struct dentry * dentry_ptr
Definition dentry.h:20
void print_dentry_tree(dentry_t *node, int depth)
Definition dentry.c:300
int resolve_dentry(char *path, dentry_ptr parent, dentry_ptr *out, uint8_t flag)
Resolves a path to a directory entry (dentry) with configurable start point and strictness.
int vxnamei(const char *path, dentry_ptr *out)
Resolves a file path to a directory entry (dentry).
@ CREATE_MISSING_ENTRY
Definition dentry.h:81
volatile uint64_t addr
Definition e1000.hpp:0
elf_section_map uintptr_t base
Definition elf.h:296
@ VFS_OK
Definition enum.h:5
struct vnode vnode_t
Definition filesystem.h:10
struct fs_data data
Definition filesystem.h:1
struct filesystem filesystem_t
Definition filesystem.h:14
#define INIT(fn)
Definition init.h:26
static struct initrd_internal_data __initrd_data
Definition initrd.c:41
static void LoadIntoVfs(dentry_ptr dentry)
static int initrd_read(vnode_t *vnode, void *buf, size_t len, size_t offset)
Definition initrd.c:88
filesystem_t * initrd_fs_impl()
struct slab_cache * initrd_internal_vnode_data_cache
Definition initrd.c:38
struct initrd_module initrd_module_t
void * kalloc(size_t size)
#define VIRT2PHYS(x)
size_t len
Definition oct2bin.h:7
void paging_reload(page_t p)
Definition paging.c:457
page_t paging_get_highest_page_map(void)
Definition paging.c:463
void vxMultipleMmap(page_t page_dir, uint64_t virt, uint64_t phys, uint64_t size, uint64_t flags)
Definition paging.c:340
#define BLOCK_SIZE
#define LOG_ERROR(mod, fmt,...)
Definition serial.h:25
#define LOG_WARN(mod, fmt,...)
Definition serial.h:27
#define LOG_INFO(mod, fmt,...)
Definition serial.h:20
#define LOG2_INFO(mod, fmt,...)
Definition serial.h:33
#define LOG_DEBUG(mod, fmt,...)
Definition serial.h:22
int strncmp(const char *s1, const char *s2, size_t n)
void memcopy(void *dest, void *src, size_t size)
kstring name
Definition dentry.h:32
struct vnode * vnode
Definition dentry.h:33
uintptr_t virt_addr
Definition initrd.c:30
spinlock_t lock
Definition initrd.c:32
uint64_t raw_addr
Definition initrd.c:29
size_t size
Definition initrd.h:30
uint64_t start
Definition initrd.h:31
char * c_str
Definition string.h:12
Definition vnode.h:59
void * ops
Definition vnode.h:64
void * vnode_private
Definition vnode.h:72
uint8_t type
Definition vnode.h:62
uint16_t permission
Definition vnode.h:65
size_t size
Definition vnode.h:63
int(* read)(vnode_t *vnode, void *buf, size_t len, size_t offset)
Definition vnode.h:30
#define NULL
Definition type.h:76
unsigned short uint16_t
Definition type.h:13
#define KERNEL_API
Definition type.h:93
unsigned long uintptr_t
Definition type.h:73
unsigned long uint64_t
Definition type.h:25
unsigned char uint8_t
Definition type.h:7
unsigned long size_t
Definition type.h:55
vnode_t * create_and_attach_vnode()
uint32_t offset
Definition virtio.h:6
@ VNODE_TYPE_FILE
Definition vnode.h:12
@ VNODE_TYPE_DIR
Definition vnode.h:13
size_t size
Definition vnode.h:3