Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add EXT4 filesystem support #42

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion defaults/fstab
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Filesystem source # Filesystem mount point # Filesystem name # Mount options # dump # fsck
/dev/sda1 / ext2
/dev/sda1 / ext4
# lazytime 0 0
2 changes: 1 addition & 1 deletion kernel/arch/x86_64/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
x86_64-y:= apic.o avx.o boot.o copy_user.o copy.o cpu.o debug.o \
x86_64-y:= apic.o avx.o boot.o copy_user.o copy.o cpu.o crc32.o debug.o \
desc_load.o disassembler.o entry.o exit.o fpu.o gdt.o idt.o interrupts.o irq.o \
isr.o kvm.o mce.o multiboot2.o mmu.o pat.o pic.o pit.o ptrace.o signal.o smbios.o \
smp_trampoline.o smp.o strace.o syscall.o thread.o tsc.o \
Expand Down
119 changes: 119 additions & 0 deletions kernel/arch/x86_64/crc32.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright (c) 2022 Pedro Falcato
* This file is part of Onyx, and is released under the terms of the MIT License
* check LICENSE at the root directory for more information
*
* SPDX-License-Identifier: MIT
*/
#include <stddef.h>
#include <stdint.h>

typedef uint32_t __attribute__((may_alias)) may_alias_uint32_t;
typedef uint64_t __attribute__((may_alias)) may_alias_uint64_t;
typedef uint16_t __attribute__((may_alias)) may_alias_uint16_t;
typedef uint8_t __attribute__((may_alias)) may_alias_uint8_t;

#define IS_BUFFER_ALIGNED_TO(buf, boundary) (((unsigned long) (buf)) & (boundary))

#define __crc32b(crc, val) __asm__("crc32b %1, %k0" : "+r"(crc) : "r"(val))
#define __crc32w(crc, val) __asm__("crc32w %1, %k0" : "+r"(crc) : "r"(val))
#define __crc32l(crc, val) __asm__("crc32l %1, %k0" : "+r"(crc) : "r"(val))
#define __crc32q(crc, val) __asm__("crc32q %1, %q0" : "+r"(crc) : "r"(val))

uint32_t crc32c_calculate_sse(const void *buffer, size_t length, uint32_t initial_value)
{
const uint8_t *buf;
uint64_t Crc;

buf = (const uint8_t *) buffer;
Crc = ~initial_value;

if (length == 0) [[unlikely]]
return 0;

/* Step 0: Align the buffer to a word boundary(at least).*/
if (IS_BUFFER_ALIGNED_TO(buf, 1))
{
__crc32b(Crc, *buf);
buf++;
length--;
}

/* Right now, nr_blocks represents the number of 16-bit blocks */
auto nr_blocks = length >> 1;

if (nr_blocks) [[likely]]
{
/* Step 1: Align to a dword boundary if we're not already */
if (IS_BUFFER_ALIGNED_TO(buf, 2))
{
__crc32w(Crc, *(may_alias_uint16_t *) buf);
buf += 2;
length -= 2;
nr_blocks--;
}

/* Now, we switched to a block_size of 32 bits(4 bytes) */
nr_blocks >>= 1;

if (nr_blocks)
{
if (IS_BUFFER_ALIGNED_TO(buf, 4))
{
__crc32l(Crc, *(may_alias_uint32_t *) buf);
buf += 4;
length -= 4;
nr_blocks--;
}

/* We're certainly 8-byte aligned right now, so we're going to
* switch the block size to 64 bytes and enter the main loop.
*/

/* Note that we save the number of 8 byte blocks for later */
auto nr_8b_blocks = nr_blocks >> 1;
nr_blocks >>= 4;

while (nr_blocks)
{
__crc32q(Crc, *(may_alias_uint64_t *) buf);
__crc32q(Crc, *((may_alias_uint64_t *) buf + 1));
__crc32q(Crc, *((may_alias_uint64_t *) buf + 2));
__crc32q(Crc, *((may_alias_uint64_t *) buf + 3));
__crc32q(Crc, *((may_alias_uint64_t *) buf + 4));
__crc32q(Crc, *((may_alias_uint64_t *) buf + 5));
__crc32q(Crc, *((may_alias_uint64_t *) buf + 6));
__crc32q(Crc, *((may_alias_uint64_t *) buf + 7));
buf += 64;
nr_blocks--;
}

/* Handle leftover 8-byte blocks */
nr_8b_blocks %= 8;
while (nr_8b_blocks)
{
__crc32q(Crc, *(may_alias_uint64_t *) buf);
nr_8b_blocks--;
buf += 8;
}

/* Now we're going to start wrapping up. */
if (length & 4)
{
__crc32l(Crc, *(may_alias_uint32_t *) buf);
buf += 4;
}
}

if (length & 2)
{
__crc32w(Crc, *(may_alias_uint16_t *) buf);
buf += 2;
}
}

if (length & 1)
__crc32b(Crc, *(may_alias_uint8_t *) buf);

return (uint32_t) ~Crc;
}
2 changes: 1 addition & 1 deletion kernel/configs/kernel.config.arm64
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CONFIG_KASLR=y
CONFIG_ASLR=y
CONFIG_EXT2=y
CONFIG_EXT4=y
CONFIG_KTRACE=y
CONFIG_UBSAN=y
CONFIG_AHCI=y
Expand Down
2 changes: 1 addition & 1 deletion kernel/configs/kernel.config.riscv
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CONFIG_KASLR=y
CONFIG_ASLR=y
CONFIG_EXT2=y
CONFIG_EXT4=y
CONFIG_KTRACE=y
CONFIG_UBSAN=y
CONFIG_AHCI=y
Expand Down
2 changes: 1 addition & 1 deletion kernel/configs/kernel.config.x86_64
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CONFIG_KASLR=y
CONFIG_ASLR=y
CONFIG_EXT2=y
CONFIG_EXT4=y
CONFIG_KTRACE=y
CONFIG_UBSAN=n
CONFIG_AHCI=y
Expand Down
31 changes: 26 additions & 5 deletions kernel/include/onyx/crc32.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,36 @@
/*
* Copyright (c) 2016, 2017 Pedro Falcato
* Copyright (c) 2016 - 2022 Pedro Falcato
* This file is part of Onyx, and is released under the terms of the MIT License
* check LICENSE at the root directory for more information
*
* SPDX-License-Identifier: MIT
*/
#ifndef _KERNEL_CRC32_H
#define _KERNEL_CRC32_H
#ifndef _ONYX_CRC32_H
#define _ONYX_CRC32_H

#include <stddef.h>
#include <stdint.h>

uint32_t crc32_calculate(uint8_t *ptr, size_t len);
uint32_t crc32_calculate_eth(uint8_t *ptr, size_t len);
uint32_t crc32_calculate(const uint8_t *ptr, size_t len);

/**
Calculates the CRC32c checksum of the given buffer.
@param[in] buffer Pointer to the buffer.
@param[in] length Length of the buffer, in bytes.
@param[in] initial_value Initial value of the CRC.
@return The CRC32c checksum.
**/
uint32_t crc32c_calculate(const void *buffer, size_t length, uint32_t initial_value);

/**
Calculates the CRC16-ANSI checksum of the given buffer.

@param[in] Buffer Pointer to the buffer.
@param[in] Length Length of the buffer, in bytes.
@param[in] InitialValue Initial value of the CRC.

@return The CRC16-ANSI checksum.
**/
uint16_t crc16_calculate(const void *Buffer, size_t Length, uint16_t InitialValue);

#endif
54 changes: 30 additions & 24 deletions kernel/include/onyx/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,41 +89,47 @@ int inode_init(struct inode *ino, bool is_reg);
#define INODE_FLAG_FREEING (1 << 4)
struct inode
{
unsigned long i_refc;
unsigned long i_refc{1};
/* TODO: We could use a lock here to protect i_flags to have
* thread-safe dirties, etc...
*/
unsigned int i_flags;
ino_t i_inode;
gid_t i_gid;
uid_t i_uid;
mode_t i_mode;
int i_type;
size_t i_size;
dev_t i_dev;
dev_t i_rdev;
time_t i_atime;
time_t i_ctime;
time_t i_mtime;
nlink_t i_nlink;
blkcnt_t i_blocks;
struct superblock *i_sb;

struct file_ops *i_fops;

struct vm_object *i_pages;
unsigned int i_flags{0};
ino_t i_inode{0};
gid_t i_gid{0};
uid_t i_uid{0};
mode_t i_mode{0};
int i_type{0};
size_t i_size{0};
dev_t i_dev{0};
dev_t i_rdev{0};
time_t i_atime{0};
time_t i_ctime{0};
time_t i_mtime{0};
nlink_t i_nlink{0};
blkcnt_t i_blocks{0};
struct superblock *i_sb{nullptr};

struct file_ops *i_fops{nullptr};

struct vm_object *i_pages{nullptr};
struct list_head i_dirty_inode_node;
void *i_flush_dev;
void *i_flush_dev{nullptr};

struct inode *i_next;
void *i_helper;
struct dentry *i_dentry; /* Only valid for directories */
struct inode *i_next{nullptr};
void *i_helper{nullptr};
struct dentry *i_dentry{nullptr}; /* Only valid for directories */
struct rwlock i_rwlock;
struct list_head i_sb_list_node;
struct list_head i_hash_list_node;
struct spinlock i_lock;

#ifdef __cplusplus

inode()
{
rwlock_init(&i_rwlock);
}

int init(mode_t mode)
{
return inode_init(this, S_ISREG(mode));
Expand Down
2 changes: 1 addition & 1 deletion kernel/kernel.config.minimal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CONFIG_KASLR=n
CONFIG_ASLR=n
CONFIG_EXT2=n
CONFIG_EXT4=n
CONFIG_KTRACE=y
CONFIG_UBSAN=n
CONFIG_AHCI=n
Expand Down
4 changes: 2 additions & 2 deletions kernel/kernel/binfmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ void *bin_do_interp(struct binfmt_args *_args)
if (!file)
{
#if 0
printk("Could not open %s\n", args.interp_path);
perror("open_vfs");
printk("Could not open %s\n", args.interp_path);
perror("open_vfs");
#endif
return nullptr;
}
Expand Down
Loading