tar_file_read
This commit is contained in:
+2
-1
@@ -13,4 +13,5 @@ symbols.S
|
||||
*.log
|
||||
build/
|
||||
compile_commands.json
|
||||
.cache/
|
||||
.cache/
|
||||
*.tar
|
||||
@@ -43,14 +43,13 @@ limine/limine:
|
||||
git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1
|
||||
$(MAKE) -C limine
|
||||
|
||||
build-iso: limine/limine $(ELFFILE)
|
||||
build-iso: limine/limine $(ELFFILE) initfs
|
||||
rm -rf iso_root
|
||||
mkdir -p iso_root/boot
|
||||
cp -v $(ELFFILE) iso_root/boot
|
||||
mkdir -p iso_root/boot/limine
|
||||
cp -v limine.conf iso_root/boot/limine
|
||||
cp $(BUILDDIR)/hello iso_root/boot/
|
||||
cp $(BUILDDIR)/pedicel iso_root/boot/
|
||||
cp calyx.tar iso_root/boot/
|
||||
mkdir -p iso_root/EFI/BOOT
|
||||
cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/
|
||||
cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/
|
||||
@@ -62,6 +61,12 @@ build-iso: limine/limine $(ELFFILE)
|
||||
iso_root -o pepper.iso
|
||||
./limine/limine bios-install pepper.iso
|
||||
|
||||
.PHONY: initfs
|
||||
initfs:
|
||||
cp $(BUILDDIR)/hello calyx/
|
||||
cp $(BUILDDIR)/pedicel calyx/
|
||||
tar cvf calyx.tar -C ./calyx .
|
||||
|
||||
.PHONY: debug
|
||||
debug:
|
||||
/usr/bin/qemu-system-x86_64 -drive file=pepper.iso -s -S -d int -D qemu.log -no-reboot -no-shutdown &
|
||||
@@ -78,4 +83,4 @@ run: build-iso
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(BUILDDIR) symbols.map symbols.S $(ELFFILE) iso_root pepper.iso limine
|
||||
rm -rf $(BUILDDIR) symbols.map symbols.S $(ELFFILE) iso_root pepper.iso limine calyx.tar
|
||||
|
||||
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
Welcome to the initial filesystem!
|
||||
@@ -45,6 +45,9 @@
|
||||
#define USER_STACK_PAGES 16 // 16*4096 = 64kb
|
||||
#define USER_CODE_START 0x400000 // like linux
|
||||
|
||||
/* fs */
|
||||
#define CALYXFS_FILES_MAX 10
|
||||
|
||||
/* paging */
|
||||
#define PAGING_MAX_PHYS 0x200000000
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* @author xamidev <xamidev@riseup.net>
|
||||
* @brief Tape archive (TAR) filesystem definitions
|
||||
* @license GPL-3.0-only
|
||||
*/
|
||||
|
||||
#ifndef TAR_H
|
||||
#define TAR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limine.h>
|
||||
|
||||
struct tar_header
|
||||
{
|
||||
char filename[100];
|
||||
char mode[8];
|
||||
char uid[8];
|
||||
char gid[8];
|
||||
char size[12];
|
||||
char mtime[12];
|
||||
char chksum[8];
|
||||
char typeflag[1];
|
||||
};
|
||||
|
||||
struct tar_file
|
||||
{
|
||||
void* address;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
unsigned int tar_parse(uint64_t address);
|
||||
int tar_init_fs(struct limine_file* file);
|
||||
struct tar_header* tar_file_lookup(const char* filename);
|
||||
void tar_file_read(struct tar_header* header, uint8_t* buf);
|
||||
|
||||
#endif
|
||||
@@ -13,5 +13,6 @@ char *strcpy(char *dest, const char *src);
|
||||
char *strcat(char *dest, const char *src);
|
||||
void strncpy(char* dst, const char* src, size_t n);
|
||||
int strncmp(const char* s1, const char* s2, size_t n);
|
||||
size_t strlen(const char *str);
|
||||
|
||||
#endif
|
||||
+1
-2
@@ -6,5 +6,4 @@ interface_branding: Welcome to the PepperOS disk!
|
||||
|
||||
comment: Default configuration (warning: spicy)
|
||||
path: boot():/boot/pepperk
|
||||
module_path: boot():/boot/hello
|
||||
module_path: boot():/boot/pedicel
|
||||
module_path: boot():/boot/calyx.tar
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* @author xamidev <xamidev@riseup.net>
|
||||
* @brief Tape archive (TAR) initial filesystem routines
|
||||
* @license GPL-3.0-only
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
TODO:
|
||||
|
||||
implement open, read, write, close for tar
|
||||
|
||||
eventually seek, stat, etc. would be nice to handle some more syscalls
|
||||
*/
|
||||
|
||||
#include <fs/tar.h>
|
||||
#include <config.h>
|
||||
#include <stdint.h>
|
||||
#include <kernel.h>
|
||||
#include <stddef.h>
|
||||
#include <string/string.h>
|
||||
#include <mem/kheap.h>
|
||||
#include <mem/utils.h>
|
||||
#include <limine.h>
|
||||
|
||||
struct tar_header* headers[CALYXFS_FILES_MAX] = {0};
|
||||
|
||||
struct tar_file archive;
|
||||
|
||||
#define TAR_BLOCK_SIZE 512
|
||||
|
||||
// To get file content, just use file_offset[file]+header_size
|
||||
// uint64_t file_offsets[CALYXFS_FILES_MAX] = {0};
|
||||
|
||||
/*
|
||||
* tar_getsize - Get the size of a file contained in a tar archive
|
||||
* @in: size attribute of a tar header
|
||||
*
|
||||
* Return:
|
||||
* <size> - Size of file in bytes
|
||||
*/
|
||||
unsigned int tar_getsize(const char *in)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
unsigned int count = 1;
|
||||
|
||||
for (unsigned int j = 11; j > 0; j--, count *= 8) {
|
||||
size += ((in[j - 1] - '0') * count);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* tar_parse - Parse a TAR file
|
||||
* @address: address of TAR file start in memory
|
||||
*
|
||||
* This function goes through all headers in a TAR file
|
||||
* and populates the header array so we can work with
|
||||
* the files contained in the archive.
|
||||
*
|
||||
* Return:
|
||||
* <i> - number of files parsed/found
|
||||
*/
|
||||
unsigned int tar_parse(uint64_t address)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < CALYXFS_FILES_MAX; i++) {
|
||||
struct tar_header *header = (struct tar_header*)address;
|
||||
|
||||
if (header->filename[0] == '\0') {
|
||||
break;
|
||||
}
|
||||
unsigned int size = tar_getsize(header->size);
|
||||
headers[i] = header;
|
||||
|
||||
DEBUG("found file %s of size %u", header->filename, size);
|
||||
uint64_t file_blocks = (size + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE;
|
||||
address += TAR_BLOCK_SIZE + (file_blocks * TAR_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* tar_init_fs - Initialize the TAR filesystem
|
||||
* @file: pointer to Limine file structure (corresponding
|
||||
* to the loaded boot module)
|
||||
*
|
||||
* This function initializes the tar_file object
|
||||
* to the values of the found TAR archive, namely
|
||||
* its address and its size.
|
||||
*
|
||||
* It then parses the archive using tar_parse,
|
||||
* so it can be looked up later.
|
||||
*
|
||||
* Return:
|
||||
* %0 - on success
|
||||
*/
|
||||
int tar_init_fs(struct limine_file* file)
|
||||
{
|
||||
DEBUG("calyxfs found at 0x%p (size=%u)", file->address, file->size);
|
||||
archive.address = file->address;
|
||||
archive.size = file->size;
|
||||
tar_parse((uint64_t)archive.address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tar_is_zeroed - Checks if a TAR header is zero
|
||||
* @header: pointer to TAR header
|
||||
*
|
||||
* Return:
|
||||
* True - TAR header is zeroed out
|
||||
* False - TAR header contains something
|
||||
*/
|
||||
bool tar_is_zeroed(struct tar_header* header)
|
||||
{
|
||||
struct tar_header zeroed = {0};
|
||||
return memcmp(header, &zeroed, sizeof(struct tar_header)) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tar_file_lookup - Find a file
|
||||
*
|
||||
* This functions looks up the @filename in the tar
|
||||
* archive.
|
||||
*
|
||||
* Return:
|
||||
* <addr> - Address of TAR header for the found file
|
||||
* %0 - file not found
|
||||
*/
|
||||
struct tar_header* tar_file_lookup(const char* filename)
|
||||
{
|
||||
if (!filename || !archive.address) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zero_counter = 0;
|
||||
struct tar_header* curr = archive.address;
|
||||
|
||||
while (zero_counter < 2) {
|
||||
if (tar_is_zeroed(curr)) {
|
||||
zero_counter++;
|
||||
curr = (struct tar_header*)((uint8_t*)curr + TAR_BLOCK_SIZE);
|
||||
continue;
|
||||
}
|
||||
|
||||
zero_counter = 0;
|
||||
|
||||
if (strncmp(filename, curr->filename, sizeof(curr->filename)) == 0) {
|
||||
DEBUG("found file %s", filename);
|
||||
return curr;
|
||||
}
|
||||
|
||||
uint64_t sz = tar_getsize(curr->size);
|
||||
uint64_t file_blocks = (sz + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE;
|
||||
curr = (struct tar_header*)((uint8_t*)curr + TAR_BLOCK_SIZE + (file_blocks * TAR_BLOCK_SIZE));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tar_file_read - Read a file contained in TAR archive
|
||||
* @header: Header of given file
|
||||
* @buf: data out buffer
|
||||
*
|
||||
* This function reads the file, using its @header, to
|
||||
* the @buf buffer. It needs to be big enough to contain
|
||||
* the file, or else a buffer overrun might happen.
|
||||
*/
|
||||
void tar_file_read(struct tar_header* header, uint8_t* buf)
|
||||
{
|
||||
if (!header || !buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t sz = tar_getsize(header->size);
|
||||
void* file_ptr = (void*)((uint8_t*)header + TAR_BLOCK_SIZE);
|
||||
|
||||
memcpy(buf, (void*)file_ptr, sz);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* @author xamidev <xamidev@riseup.net>
|
||||
* @brief Virtual filesystem (VFS) layer
|
||||
* @license GPL-3.0-only
|
||||
*/
|
||||
|
||||
/*
|
||||
Around here we'll want to have some file operations struct with
|
||||
function pointers (read, write, open, close) for different filesystems.
|
||||
|
||||
At init, the function pointers will be assigned to the corresponding
|
||||
filesystem-dependent functions.
|
||||
|
||||
That way we have a nice abstraction layer and can just do calls no matter
|
||||
the underlying fs.
|
||||
*/
|
||||
+13
-8
@@ -25,6 +25,7 @@
|
||||
#include <io/term/flanterm_backends/fb.h>
|
||||
#include <arch/x86.h>
|
||||
#include <boot/boot.h>
|
||||
#include <fs/tar.h>
|
||||
|
||||
// Limine version used
|
||||
__attribute__((used, section(".limine_requests")))
|
||||
@@ -120,16 +121,20 @@ void kmain()
|
||||
idle_proc = process_create("idle", (void*)idle_main, 0);
|
||||
|
||||
if (!boot_ctx.module) {
|
||||
panic(NULL, "could not load 'hello' executable :(");
|
||||
panic(NULL, "could not load calyx filesystem!");
|
||||
}
|
||||
if (boot_ctx.module->module_count == 2) {
|
||||
file = boot_ctx.module->modules[0];
|
||||
DEBUG("file: addr=%p size=%u", file->address, file->size);
|
||||
process_create_user(file, "hello");
|
||||
|
||||
file = boot_ctx.module->modules[1];
|
||||
process_create_user(file, "pedicel");
|
||||
}
|
||||
file = boot_ctx.module->modules[0];
|
||||
tar_init_fs(file);
|
||||
|
||||
/* DANGER ZONE (tests)*/
|
||||
struct tar_header* header = tar_file_lookup("./welcome.txt");
|
||||
|
||||
uint8_t buf[1000] = {0};
|
||||
tar_file_read(header, buf);
|
||||
DEBUG("-BEGIN BUFFER-%s-END BUFFER-", buf);
|
||||
/* END DANGER ZONE */
|
||||
|
||||
scheduler_init();
|
||||
|
||||
printf(PEPPEROS_SPLASH);
|
||||
|
||||
@@ -98,4 +98,18 @@ int strncmp(const char* s1, const char* s2, size_t n)
|
||||
else {
|
||||
return ( *(unsigned char *)s1 - *(unsigned char *)s2 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* strlen - Get a string's length (BSD implementation)
|
||||
* @str: null-terminated string
|
||||
*
|
||||
* Return:
|
||||
* <size> - length of the string in bytes
|
||||
*/
|
||||
size_t strlen(const char *str)
|
||||
{
|
||||
const char *s;
|
||||
for (s = str; *s; ++s);
|
||||
return (s - str);
|
||||
}
|
||||
Reference in New Issue
Block a user