19 Commits

Author SHA1 Message Date
6c32c430d0 feat: start of paging setup 2022-05-14 17:01:10 +02:00
e850dabc8b feat: small code optimisations 2022-05-14 16:59:04 +02:00
6d898c07e8 feat: added not implemented function 2021-10-07 19:29:49 +02:00
03f0ec6f88 feat: Vfs and Ext2 support. Code style/attribute improvements
Added VFS and Ext2 support.
Optimized attributes of methods to improve code highlighting.
Printf attribute, malloc attribute, etc.
2021-10-06 21:45:15 +02:00
073051c99e feat: cleanup init code, small other refactors 2021-09-01 21:43:21 +02:00
e693b12915 feat: added missing lapic code 2021-08-30 19:58:50 +02:00
e37222c346 feat: added basic ACPI support using LAI 2021-08-30 19:56:36 +02:00
462dd90890 feat: removed unused cmake directory 2021-08-30 19:50:28 +02:00
a7bd154c32 feat: made string.h and string.c more compliant 2021-08-30 19:47:39 +02:00
ad023a8119 Updated pic init 2021-08-22 19:59:55 +02:00
6b0f6ddfb7 feat added init function 2021-08-13 21:07:40 +02:00
8187265735 feat: free the name of the task when it is ended 2021-08-13 08:18:35 +02:00
f047e692c9 feat: moved file system code around 2021-08-12 21:44:10 +02:00
c172a5cb8a feat: added state to ps output 2021-08-12 20:42:06 +02:00
3034a5d417 feat: added ps command 2021-08-12 20:31:11 +02:00
94c6332e27 feat: added task names 2021-08-12 20:22:00 +02:00
be71f9a7e9 feat: added reaper and suicide support 2021-08-06 22:00:00 +02:00
ee4338fedd feat: added some comments to command.c 2021-08-06 20:50:38 +02:00
8152ad6e9a feat: added sling url decomposition 2021-03-26 22:16:59 +01:00
86 changed files with 2855 additions and 1697 deletions

6
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "acpica"]
path = acpica
url = https://github.com/acpica/acpica
[submodule "lai"]
path = lai
url = https://github.com/managarm/lai.git

View File

@@ -7,37 +7,23 @@ SET(CMAKE_C_COMPILER ${COMPILER_RT}/i686-elf-gcc)
SET(CMAKE_ASM_COMPILER ${COMPILER_RT}/i686-elf-gcc)
# Optionally enable cmake debugging
#SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(CMAKE_VERBOSE_MAKEFILE ON)
# Set compile flags
SET(CMAKE_C_FLAGS "-g -ffreestanding -Wall -Wextra -fno-exceptions -fstack-protector -fno-pie -m32")
SET(CMAKE_ASM_FLAGS "${CFLAGS} -m32 -x assembler-with-cpp")
SET(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_LIST_DIR}/linker.ld -lgcc -ffreestanding -nostdlib -no-pie")
SET(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_LIST_DIR}/linker.ld -nostdlib -lgcc")
include_directories(BEFORE include)
include_directories(AFTER acpica/source/include)
include_directories(AFTER include lai/include)
set(CMAKE_C_STANDARD 99)
FILE(GLOB lai lai/core/*.c lai/helpers/*.c lai/driver/*.c)
FILE(GLOB_RECURSE kernel_src kernel/**.c)
FILE(GLOB_RECURSE kernel_asm kernel/**.S)
FILE(GLOB_RECURSE boot_asm boot/boot.S)
FILE(GLOB_RECURSE acpi_ca_src
acpica/source/components/dispatcher/*.c
acpica/source/components/events/*.c
acpica/source/components/executer/*.c
acpica/source/components/namespace/*.c
acpica/source/components/parser/*.c
acpica/source/components/hardware/*.c
acpica/source/components/tables/*.c
acpica/source/components/utilities/*.c)
get_filename_component(utprint_full_path acpica/source/components/utilities/utprint.c ABSOLUTE)
LIST(REMOVE_ITEM acpi_ca_src ${utprint_full_path})
add_compile_definitions(__kernel__)
add_compile_definitions(__KERNEL__)
add_compile_definitions(__MYKE__)
# Run IDE in DMA mode if available (NYI)
#add_compile_definitions(IDE_ENABLE_INTERRUPT)
@@ -46,9 +32,11 @@ add_compile_definitions(ENABLE_SELF_TEST) # Support for pretty printing pci cla
add_compile_definitions(ENABLE_PCIPP) # Support for pretty printing pci class/subclass/interface
add_compile_definitions(K_SHELL)
add_executable(my-kernel.bin ${kernel_src} ${kernel_asm} ${boot_asm} ${acpi_ca_src})
# find libgcc.a
add_library(libgcc STATIC IMPORTED)
set_target_properties(libgcc PROPERTIES IMPORTED_LOCATION ${COMPILER_RT}/../lib/gcc/i686-elf/10.2.0/libgcc.a)
add_executable(my-kernel.bin ${kernel_src} ${kernel_asm} ${boot_asm} ${lai})
target_link_libraries(my-kernel.bin libgcc)
set_source_files_properties(${kernel_src} PROPERTIES LANGUAGE C COMPILE_FLAGS "")
set_target_properties(my-kernel.bin PROPERTIES LINKER_LANGUAGE C PREFIX "" SUFFIX "" LINK_FLAGS "")
set_target_properties(my-kernel.bin PROPERTIES LINKER_LANGUAGE C PREFIX "" SUFFIX "" LINK_FLAGS "")

1
acpica

Submodule acpica deleted from 63db9761a6

View File

@@ -19,7 +19,7 @@ forced to be within the first 8 KiB of the kernel file.
.long CHECKSUM
#.include "gdt.S"
.section .data
.section .data.boot
gdt:
.quad 0x0000000000000000
.quad 0x00CF9A000000FFFF
@@ -42,7 +42,7 @@ System V ABI standard and de-facto extensions. The compiler will assume the
stack is properly aligned and failure to align the stack will result in
undefined behavior.
*/
.section .bss
.section .bss.boot
.align 16
stack_bottom:
.skip 16384 # 16 KiB
@@ -53,7 +53,7 @@ The linker script specifies _start as the entry point to the kernel and the
bootloader will jump to this position once the kernel has been loaded. It
doesn't make sense to return from this function as the bootloader is gone.
*/
.section .text
.section .text.boot
.global _start
.type _start, @function
_start:
@@ -103,6 +103,25 @@ _start:
continue_boot:
sti
// setting up paging
// id map first 4MB using PSE. With
movl $135, kernel_page_directory - 0xC0000000
movl $135, kernel_page_directory - 0xC0000000 + 3072
// load into cr3
movl $kernel_page_directory - 0xC0000000, %eax
movl %eax, %cr3
// enable PSE TODO validate if PSE is actually supported
movl %cr4, %eax
orl $0x10, %eax
movl %eax, %cr4
// enable paging
movl %cr0, %eax
orl $0x80000000, %eax
movl %eax, %cr0
nop
pushl 0
popl %eax
/*
Enter the high-level kernel. The ABI requires the stack is 16-byte
aligned at the time of the call instruction (which afterwards pushes

View File

@@ -1,10 +0,0 @@
FIND_PATH(GCC_INCLUDES_INCLUDE_DIR cpuid.h
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include
)
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set APACHE_FOUND to TRUE if
# all listed variables are TRUE
find_package_handle_standard_args(GCC_INCLUDES DEFAULT_MSG GCC_INCLUDES_INCLUDE_DIR )
MARK_AS_ADVANCED(GCC_INCLUDES_INCLUDE_DIR)

View File

@@ -1,394 +0,0 @@
/******************************************************************************
*
* Name: acenv.h - Host and compiler configuration
*
*****************************************************************************/
/******************************************************************************
*
* 1. Copyright Notice
*
* Some or all of this work - Copyright (c) 1999 - 2016, Intel Corp.
* All rights reserved.
*
* 2. License
*
* 2.1. This is your license from Intel Corp. under its intellectual property
* rights. You may have additional license terms from the party that provided
* you this software, covering your right to use that party's intellectual
* property rights.
*
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
* copy of the source code appearing in this file ("Covered Code") an
* irrevocable, perpetual, worldwide license under Intel's copyrights in the
* base code distributed originally by Intel ("Original Intel Code") to copy,
* make derivatives, distribute, use and display any portion of the Covered
* Code in any form, with the right to sublicense such rights; and
*
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
* license (with the right to sublicense), under only those claims of Intel
* patents that are infringed by the Original Intel Code, to make, use, sell,
* offer to sell, and import the Covered Code and derivative works thereof
* solely to the minimum extent necessary to exercise the above copyright
* license, and in no event shall the patent license extend to any additions
* to or modifications of the Original Intel Code. No other license or right
* is granted directly or by implication, estoppel or otherwise;
*
* The above copyright and patent license is granted only if the following
* conditions are met:
*
* 3. Conditions
*
* 3.1. Redistribution of Source with Rights to Further Distribute Source.
* Redistribution of source code of any substantial portion of the Covered
* Code or modification with rights to further distribute source must include
* the above Copyright Notice, the above License, this list of Conditions,
* and the following Disclaimer and Export Compliance provision. In addition,
* Licensee must cause all Covered Code to which Licensee contributes to
* contain a file documenting the changes Licensee made to create that Covered
* Code and the date of any change. Licensee must include in that file the
* documentation of any changes made by any predecessor Licensee. Licensee
* must include a prominent statement that the modification is derived,
* directly or indirectly, from Original Intel Code.
*
* 3.2. Redistribution of Source with no Rights to Further Distribute Source.
* Redistribution of source code of any substantial portion of the Covered
* Code or modification without rights to further distribute source must
* include the following Disclaimer and Export Compliance provision in the
* documentation and/or other materials provided with distribution. In
* addition, Licensee may not authorize further sublicense of source of any
* portion of the Covered Code, and must include terms to the effect that the
* license from Licensee to its licensee is limited to the intellectual
* property embodied in the software Licensee provides to its licensee, and
* not to intellectual property embodied in modifications its licensee may
* make.
*
* 3.3. Redistribution of Executable. Redistribution in executable form of any
* substantial portion of the Covered Code or modification must reproduce the
* above Copyright Notice, and the following Disclaimer and Export Compliance
* provision in the documentation and/or other materials provided with the
* distribution.
*
* 3.4. Intel retains all right, title, and interest in and to the Original
* Intel Code.
*
* 3.5. Neither the name Intel nor any other trademark owned or controlled by
* Intel shall be used in advertising or otherwise to promote the sale, use or
* other dealings in products derived from or relating to the Covered Code
* without prior written authorization from Intel.
*
* 4. Disclaimer and Export Compliance
*
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
* LIMITED REMEDY.
*
* 4.3. Licensee shall not export, either directly or indirectly, any of this
* software or system incorporating such software without first obtaining any
* required license or other approval from the U. S. Department of Commerce or
* any other agency or department of the United States Government. In the
* event Licensee exports any such software from the United States or
* re-exports any such software from a foreign destination, Licensee shall
* ensure that the distribution and export/re-export of the software is in
* compliance with all laws, regulations, orders, or other restrictions of the
* U.S. Export Administration Regulations. Licensee agrees that neither it nor
* any of its subsidiaries will export/re-export any technical data, process,
* software, or service, directly or indirectly, to any country for which the
* United States government or any agency thereof requires an export license,
* other governmental approval, or letter of assurance, without first obtaining
* such license, approval or letter.
*
*****************************************************************************/
#ifndef __ACMYKE_H__
#define __ACMYKE_H__
/*
* Environment configuration. The purpose of this file is to interface ACPICA
* to the local environment. This includes compiler-specific, OS-specific,
* and machine-specific configuration.
*/
/* Types for ACPI_MUTEX_TYPE */
#define ACPI_BINARY_SEMAPHORE 0
#define ACPI_OSL_MUTEX 1
/* Types for DEBUGGER_THREADING */
#define DEBUGGER_SINGLE_THREADED 0
#define DEBUGGER_MULTI_THREADED 1
/******************************************************************************
*
* Configuration for ACPI tools and utilities
*
*****************************************************************************/
/* Common application configuration. All single threaded except for AcpiExec. */
#if (defined ACPI_ASL_COMPILER) || \
(defined ACPI_BIN_APP) || \
(defined ACPI_DUMP_APP) || \
(defined ACPI_HELP_APP) || \
(defined ACPI_NAMES_APP) || \
(defined ACPI_SRC_APP) || \
(defined ACPI_XTRACT_APP) || \
(defined ACPI_EXAMPLE_APP)
#define ACPI_APPLICATION
#define ACPI_SINGLE_THREADED
#endif
/* iASL configuration */
#ifdef ACPI_ASL_COMPILER
#define ACPI_DEBUG_OUTPUT
#define ACPI_CONSTANT_EVAL_ONLY
#define ACPI_LARGE_NAMESPACE_NODE
#define ACPI_DATA_TABLE_DISASSEMBLY
#define ACPI_32BIT_PHYSICAL_ADDRESS
#define ACPI_DISASSEMBLER 1
#endif
/* AcpiExec configuration. Multithreaded with full AML debugger */
#ifdef ACPI_EXEC_APP
#define ACPI_APPLICATION
#define ACPI_FULL_DEBUG
#define ACPI_MUTEX_DEBUG
#define ACPI_DBG_TRACK_ALLOCATIONS
#endif
/* AcpiHelp configuration. Error messages disabled. */
#ifdef ACPI_HELP_APP
#define ACPI_NO_ERROR_MESSAGES
#endif
/* AcpiNames configuration. Debug output enabled. */
#ifdef ACPI_NAMES_APP
#define ACPI_DEBUG_OUTPUT
#endif
/* AcpiExec/AcpiNames/Example configuration. Native RSDP used. */
#if (defined ACPI_EXEC_APP) || \
(defined ACPI_EXAMPLE_APP) || \
(defined ACPI_NAMES_APP)
#define ACPI_USE_NATIVE_RSDP_POINTER
#endif
/* AcpiDump configuration. Native mapping used if provided by the host */
#ifdef ACPI_DUMP_APP
#define ACPI_USE_NATIVE_MEMORY_MAPPING
#define USE_NATIVE_ALLOCATE_ZEROED
#endif
/* AcpiNames/Example configuration. Hardware disabled */
#if (defined ACPI_EXAMPLE_APP) || \
(defined ACPI_NAMES_APP)
#define ACPI_REDUCED_HARDWARE 1
#endif
/* Linkable ACPICA library. Two versions, one with full debug. */
#ifdef ACPI_LIBRARY
#define ACPI_USE_LOCAL_CACHE
#define ACPI_DEBUGGER 1
#define ACPI_DISASSEMBLER 1
#ifdef _DEBUG
#define ACPI_DEBUG_OUTPUT
#endif
#endif
/* Common for all ACPICA applications */
#ifdef ACPI_APPLICATION
#define ACPI_USE_SYSTEM_CLIBRARY
#define ACPI_USE_LOCAL_CACHE
#endif
/* Common debug/disassembler support */
#ifdef ACPI_FULL_DEBUG
#define ACPI_DEBUG_OUTPUT
#define ACPI_DEBUGGER 1
#define ACPI_DISASSEMBLER 1
#endif
/*! [Begin] no source code translation */
/******************************************************************************
*
* Host configuration files. The compiler configuration files are included
* by the host files.
*
*****************************************************************************/
#define ACPI_MACHINE_WIDTH 32
#define ACPI_DEBUG_OUTPUT
#define ACPI_USE_LOCAL_CACHE
#define ACPI_REDUCED_HARDWARE TRUE
#define ACPI_USE_SYSTEM_CLIBRARY
#define ACPI_USE_SYSTEM_INTTYPES
#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \
asm("divl %2;" \
: "=a"(q32), "=d"(r32) \
: "r"(d32), \
"0"(n_lo), "1"(n_hi))
#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \
asm("shrl $1,%2;" \
"rcrl $1,%3;" \
:"=r"(n_hi), "=r"(n_lo) \
:"0"(n_hi), "1"(n_lo))
#define UINT8 uint8_t
#define INT8 int8_t
#define UINT16 uint16_t
#define INT16 int16_t
#define UINT32 uint32_t
#define INT32 int32_t
#define UINT64 uint64_t
#define INT64 int64_t
#define BOOLEAN uint8_t
#include <sys/types.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
/*! [End] no source code translation !*/
/******************************************************************************
*
* Setup defaults for the required symbols that were not defined in one of
* the host/compiler files above.
*
*****************************************************************************/
/* 64-bit data types */
#ifndef COMPILER_DEPENDENT_INT64
#define COMPILER_DEPENDENT_INT64 long long
#endif
#ifndef COMPILER_DEPENDENT_UINT64
#define COMPILER_DEPENDENT_UINT64 unsigned long long
#endif
/* Type of mutex supported by host. Default is binary semaphores. */
#ifndef ACPI_MUTEX_TYPE
#define ACPI_MUTEX_TYPE ACPI_OSL_MUTEX
#endif
/* Global Lock acquire/release */
#ifndef ACPI_ACQUIRE_GLOBAL_LOCK
#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acquired) Acquired = 1
#endif
#ifndef ACPI_RELEASE_GLOBAL_LOCK
#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Pending) Pending = 0
#endif
/* Flush CPU cache - used when going to sleep. Wbinvd or similar. */
#ifndef ACPI_FLUSH_CPU_CACHE
#define ACPI_FLUSH_CPU_CACHE()
#endif
/* "inline" keywords - configurable since inline is not standardized */
#ifndef ACPI_INLINE
#define ACPI_INLINE
#endif
/*
* Configurable calling conventions:
*
* ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads)
* ACPI_EXTERNAL_XFACE - External ACPI interfaces
* ACPI_INTERNAL_XFACE - Internal ACPI interfaces
* ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces
*/
#ifndef ACPI_SYSTEM_XFACE
#define ACPI_SYSTEM_XFACE
#endif
#ifndef ACPI_EXTERNAL_XFACE
#define ACPI_EXTERNAL_XFACE
#endif
#ifndef ACPI_INTERNAL_XFACE
#define ACPI_INTERNAL_XFACE
#endif
#ifndef ACPI_INTERNAL_VAR_XFACE
#define ACPI_INTERNAL_VAR_XFACE
#endif
/*
* Debugger threading model
* Use single threaded if the entire subsystem is contained in an application
* Use multiple threaded when the subsystem is running in the kernel.
*
* By default the model is single threaded if ACPI_APPLICATION is set,
* multi-threaded if ACPI_APPLICATION is not set.
*/
#ifndef DEBUGGER_THREADING
#if !defined (ACPI_APPLICATION) || defined (ACPI_EXEC_APP)
#define DEBUGGER_THREADING DEBUGGER_MULTI_THREADED
#else
#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED
#endif
#endif /* !DEBUGGER_THREADING */
/******************************************************************************
*
* C library configuration
*
*****************************************************************************/
#ifndef ACPI_FILE
#ifdef ACPI_APPLICATION
#include <stdio.h>
#define ACPI_FILE FILE *
#define ACPI_FILE_OUT stdout
#define ACPI_FILE_ERR stderr
#else
#define ACPI_FILE void *
#define ACPI_FILE_OUT NULL
#define ACPI_FILE_ERR NULL
#endif /* ACPI_APPLICATION */
#endif /* ACPI_FILE */
#ifndef ACPI_INIT_FUNCTION
#define ACPI_INIT_FUNCTION
#endif
#endif /* __ACMYKE_H__ */

View File

@@ -1,16 +0,0 @@
//
// Created by rick on 26-03-21.
//
#ifndef NEW_KERNEL_ACPI_H
#define NEW_KERNEL_ACPI_H
// override acpi.h from ACPICA
// include custom version of acenv.h
#include <platform/acenv.h>
// continue with base acpi.h
#include_next <acpi.h>
#endif //NEW_KERNEL_ACPI_H

View File

@@ -1,12 +0,0 @@
//
// Created by rick on 24-03-21.
//
#ifndef NEW_KERNEL_ACPICA_H
#define NEW_KERNEL_ACPICA_H
#include <acmyke.h>
#include <acpi.h>
#include <accommon.h>
#endif //NEW_KERNEL_ACPICA_H

View File

@@ -11,6 +11,7 @@
// function
#define att_noreturn __attribute((noreturn))
#define att_cdecl __attribute((cdecl))
#define att_unused __attribute((unused))
// structure
#define att_packed __attribute((packed))
// field

View File

@@ -1,16 +0,0 @@
//
// Created by rick on 25-03-21.
//
#ifndef NEW_KERNEL_ACPI_H
#define NEW_KERNEL_ACPI_H
#include <attributes.h>
void acpi_init_task();
void att_noreturn acpi_shutdown();
void att_noreturn acpi_restart();
#endif //NEW_KERNEL_ACPI_H

10
include/myke/acpi/acpi.h Normal file
View File

@@ -0,0 +1,10 @@
//
// Created by rick on 22-08-21.
//
#ifndef NEW_KERNEL_ACPI_H
#define NEW_KERNEL_ACPI_H
void* acpi_find_table_by_name(const char* name, int skip);
#endif //NEW_KERNEL_ACPI_H

View File

@@ -0,0 +1,256 @@
//
// Created by rick on 22-08-21.
//
#ifndef NEW_KERNEL_STRUCTURES_H
#define NEW_KERNEL_STRUCTURES_H
#include <attributes.h>
#include <stdbool.h>
#include <sys/types.h>
#define RDSP_SIGNATURE_LENGTH 8
#define RSDP_SIGNATURE "RSD PTR "
enum generic_address_structure_address_space {
system_memory = 0,
system_io = 1,
pci_config_space = 2,
embedded_controller = 3,
system_management_bus = 4,
system_cmos = 5,
pci_device_bar = 6,
ipmi = 7,
gpio = 8,
gsb = 9,
pmc = 0x0A
};
enum generic_address_structure_access_size {
undefined = 0,
uint8 = 1,
uint16 = 2,
uint32 = 3,
uint64 = 4,
};
struct generic_address_structure {
uint8_t address_space;
uint8_t bit_width;
uint8_t bit_offset;
uint8_t access_size;
uint64_t address;
};
struct acpi_rsdp_descriptor {
char signature[8];
uint8_t checksum;
char oem_id[6];
uint8_t revision;
uint32_t rsdt_address;
} att_packed;
struct acpi_rsdp_descriptor_20 {
struct acpi_rsdp_descriptor rsdp;
uint32_t length;
uint64_t xsdt_address;
uint8_t extended_checksum;
uint32_t: 24; // reserved
} att_packed;
struct acpi_sdt_header {
char signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oem_id[6];
char oem_table_id[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
} att_packed;
struct acpi_rsdt {
struct acpi_sdt_header header;
uint32_t pointer_to_other_sdt[];
} att_packed;
struct acpi_xsdt {
struct acpi_sdt_header header;
uint64_t pointer_to_other_sdt[];
} att_packed;
struct acpi_fadt {
struct acpi_sdt_header header;
uint32_t firmware_ctrl;
uint32_t dsdt;
// field used in ACPI 1.0; no longer in use, for compatibility only
uint8_t: 8;
uint8_t preferred_power_management_profile;
uint16_t sci_interrupt;
uint32_t smi_command_port;
uint8_t acpi_enable;
uint8_t acpi_disable;
uint8_t s4bios_req;
uint8_t pstate_control;
uint32_t pm1a_event_block;
uint32_t pm1b_event_block;
uint32_t pm1a_control_block;
uint32_t pm1b_control_block;
uint32_t pm2_control_block;
uint32_t pm_timer_block;
uint32_t gpe0_block;
uint32_t gpe1_block;
uint8_t pm1_event_length;
uint8_t pm1_control_length;
uint8_t pm2_control_length;
uint8_t pm_timer_length;
uint8_t gpe0_length;
uint8_t gpe1_length;
uint8_t gpe1_base;
uint8_t cstate_control;
uint16_t worst_c2_latency;
uint16_t worst_c3_latency;
uint16_t flush_size;
uint16_t flush_stride;
uint8_t duty_offset;
uint8_t duty_width;
uint8_t day_alarm;
uint8_t month_alarm;
uint8_t century;
// reserved in ACPI 1.0; used since ACPI 2.0+
uint16_t boot_architecture_flags;
uint8_t: 8;
uint32_t flags;
// 12 byte structure; see below for details
struct generic_address_structure reset_reg;
uint8_t reset_value;
uint16_t arm_boot_arch;
uint8_t fadt_minor_version;
// 64bit pointers - Available on ACPI 2.0+
uint64_t x_firmware_control;
uint64_t x_dsdt;
struct generic_address_structure x_pm1a_event_block;
struct generic_address_structure x_pm1b_event_block;
struct generic_address_structure x_pm1a_control_block;
struct generic_address_structure x_pm1b_control_block;
struct generic_address_structure x_pm2_control_block;
struct generic_address_structure x_pm_timer_block;
struct generic_address_structure x_gpe0_block;
struct generic_address_structure x_gpe1_block;
struct generic_address_structure sleep_control_register;
struct generic_address_structure sleep_status_register;
uint64_t hypervisor_id;
} att_packed;
#define MADT_TYPE_PROCESSOR_LOCAL_APIC 0
#define MADT_TYPE_IO_APIC 1
#define MADT_TYPE_IO_APIC_INTERRUPT_SOURCE_OVERRIDE 2
#define MADT_TYPE_IO_APIC_NON_MASKABLE_INTERRUPT_SOURCE 3
#define MADT_TYPE_LOCAL_APIC_NON_MASKABLE_INTERRUPTS 4
#define MADT_TYPE_LOCAL_APIC_ADDRESS_OVERRIDE 5
#define MADT_TYPE_PROCESSOR_LOCAL_X2_APIC 9
union madt_local_apic_flags {
uint32_t flags_int;
struct {
bool processor_enabled: 1;
bool online_capable: 1;
} flags;
};
union madt_interrupt_flags {
uint16_t flags_int;
struct {
bool: 1; // 1
bool active_low: 1; // 2
bool: 1; // 4
bool level_triggered: 1; // 8
} att_packed;
};
struct acpi_madt {
struct acpi_sdt_header header;
uint32_t local_apic_addr;
union {
uint32_t flags_int;
struct {
bool dual_8259_legacy_pics: 1;
};
};
uint8_t entries[];
} att_packed;
struct acpi_madt_entry_header {
uint8_t type;
uint8_t length;
} att_packed;
struct acpi_madt_local_apic { // type 0
struct acpi_madt_entry_header header;
uint8_t processor_id;
uint8_t apic_id;
union madt_local_apic_flags flags;
} att_packed;
struct acpi_madt_io_apic { // type 1
struct acpi_madt_entry_header header;
uint8_t apic_id;
uint8_t: 8; // reserved
uint32_t io_apic_address;
uint32_t global_system_interrupt_base;
} att_packed;
struct acpi_madt_io_apic_interrupt_source_override { // type 2
struct acpi_madt_entry_header header;
uint8_t bus_source;
uint8_t irq_source;
uint32_t global_system_interrupt;
union madt_interrupt_flags flags;
} att_packed;
struct acpi_madt_io_apic_non_maskable_interrupt { // type 3
struct acpi_madt_entry_header header;
uint8_t nmi_source;
uint8_t: 8; // reserved
union madt_interrupt_flags flags;
uint32_t global_system_interrupt;
} att_packed;
struct acpi_madt_local_apic_non_maskable_interrupts {
struct acpi_madt_entry_header header;
uint8_t acpi_processor_id;
union madt_interrupt_flags flags;
uint8_t lint_no;
} att_packed;
struct acpi_madt_local_apic_address_override {
struct acpi_madt_entry_header header;
uint16_t: 16; // reserved
uint64_t physical_address_local_apic;
} att_packed;
struct acpi_madt_processor_local_x2_apic {
struct acpi_madt_entry_header header;
uint16_t: 16; // reserved
uint32_t processors_local_x2_apic_id;
union madt_local_apic_flags flags;
uint32_t acpi_id;
} att_packed;
struct acpi_type {
char name[4];
char *description;
void (*handle_table)(const struct acpi_sdt_header *addr);
};
#endif //NEW_KERNEL_STRUCTURES_H

View File

@@ -9,6 +9,4 @@
void store_bootloader_info(multiboot_info_t *multiboot_info);
void main_loop(void *data);
#endif //NEW_KERNEL_COMMAND_H

View File

@@ -7,74 +7,13 @@
#include <stdbool.h>
typedef struct {
bool sse3: 1;
bool pclmul: 1;
bool dtes64: 1;
bool monitor: 1;
bool ds_cpl: 1;
bool vmx: 1;
bool smx: 1;
bool est: 1;
bool tm2: 1;
bool ssse3: 1;
bool cid: 1;
bool reserved: 1;
bool fma: 1;
bool cx16: 1;
bool etprd: 1;
bool pdcm: 1;
bool pcide: 1;
bool dca: 1;
bool sse4_1: 1;
bool sse4_2: 1;
bool x2APIC: 1;
bool movbe: 1;
bool popcnt: 1;
bool reserved2: 1;
bool aes: 1;
bool xsave: 1;
bool osxsave: 1;
bool avx: 1;
} cpu_features_ecx;
enum {
CPUID_VENDOR_ID = 0x00,
CPUID_FEATURE_FLAGS = 0x01,
CPUID_CACHE
};
typedef struct {
bool fpu: 1;
bool vme: 1;
bool de: 1;
bool pse: 1;
bool tsc: 1;
bool msr: 1;
bool pae: 1;
bool mce: 1;
bool cx8: 1;
bool apic: 1;
bool reserved: 1;
bool sep: 1;
bool mtrr: 1;
bool pge: 1;
bool mca: 1;
bool cmov: 1;
bool pat: 1;
bool pse36: 1;
bool psn: 1;
bool clf: 1;
bool reserved2: 1;
bool dtes: 1;
bool acpi: 1;
bool mmx: 1;
bool fxsr: 1;
bool sse: 1;
bool sse2: 1;
bool ss: 1;
bool htt: 1;
bool tm1: 1;
bool ia64: 1;
bool pbe: 1;
} cpu_features_edx;
enum cpu_features {
enum {
CPUID_FEAT_ECX_SSE3 = 1 << 0,
CPUID_FEAT_ECX_PCLMUL = 1 << 1,
CPUID_FEAT_ECX_DTES64 = 1 << 2,
@@ -134,6 +73,8 @@ enum cpu_features {
CPUID_FEAT_EDX_PBE = 1 << 31
};
static bool has_apic();
void cpuidx_print_info();
#endif //NEW_KERNEL_CPUIDX_H

23
include/myke/cpu/lapic.h Normal file
View File

@@ -0,0 +1,23 @@
//
// Created by rick on 23-08-21.
//
#ifndef NEW_KERNEL_LAPIC_H
#define NEW_KERNEL_LAPIC_H
#include <sys/types.h>
#define LAPIC_REG_ID 0x20
#define LAPIC_REG_VERSION 0x30
void lapic_set_addr(uint32_t addr);
void lapic_write(uint32_t offset, uint32_t value);
uint32_t lapic_read(uint32_t offset);
uint32_t lapic_get_id();
uint32_t lapic_get_version();
#endif //NEW_KERNEL_LAPIC_H

17
include/myke/cpu/pic.h Normal file
View File

@@ -0,0 +1,17 @@
//
// Created by rick on 22-08-21.
//
#ifndef NEW_KERNEL_PIC_H
#define NEW_KERNEL_PIC_H
#include <stdbool.h>
#include <sys/types.h>
void pic_init(uint8_t isr_offset);
void pic_set_mask(uint16_t mask);
void pic_eoi(bool slave);
#endif //NEW_KERNEL_PIC_H

View File

@@ -7,12 +7,12 @@
#include <sys/types.h>
int init_timer(uint32_t freq);
int pit_int_frequency(uint32_t freq);
void print_current_tick();
uint32_t timer_get_tick();
uint32_t pit_get_tick();
void sleep(uint32_t milliseconds);
void pit_sleep(uint32_t milliseconds);
#endif //MY_KERNEL_TIMER_H

View File

@@ -19,8 +19,6 @@ typedef struct KeyEvent_t {
char getc();
void init_keyboard();
//const char *key_code_to_string(KeyCode key);
KeyEvent *get_next_event();

View File

@@ -1,12 +0,0 @@
//
// Created by rick on 28-01-21.
//
#ifndef NEW_KERNEL_SERIAL_H
#define NEW_KERNEL_SERIAL_H
int serial_init();
void serial_kprint(const char *msg);
#endif //NEW_KERNEL_SERIAL_H

View File

@@ -27,8 +27,4 @@
#define VGA_COL_MAX 80
#define VGA_ROW_MAX 25
void vga_clear_screen();
void vga_kprint(const char *msg);
#endif //MY_KERNEL_VGASCREEN_H

View File

@@ -17,6 +17,4 @@ void kprint(const char *msg);
void kprint_sync(const char *msg);
void kprint_init();
void kprint_start_task();
void kprint_init();

View File

@@ -21,4 +21,6 @@ void att_noreturn k_panics(const char *msg);
void att_noreturn k_panic();
void att_noreturn k_not_implemented();
#endif //NEW_KERNEL_LIBK_H

View File

@@ -12,6 +12,7 @@
#define SYSCALL_YIELD_JOB 0x02
#define SYSCALL_YIELD_IRQ 0x03
#define SYSCALL_SUSPEND 0x04
#define SYSCALL_KILL_SELF 0x05
void att_noreturn syscall_start_scheduler();
@@ -21,4 +22,6 @@ void syscall_yield_irq(uint16_t irq);
void syscall_job_suspend();
void syscall_kill_self();
#endif //NEW_KERNEL_SYSCALL_H

View File

@@ -7,7 +7,7 @@
// retrieved from https://github.com/blanham/liballoc
#include <sys/types.h>
void *malloc(size_t);
void __attribute__((assume_aligned (16), alloc_size (1), malloc)) *malloc(size_t);
void *realloc(void *, size_t);

View File

@@ -5,4 +5,39 @@
#ifndef NEW_KERNEL_PAGING_H
#define NEW_KERNEL_PAGING_H
#define PAGING_MASK_4K 0xFFFFF000
#define PAGING_MASK_4M 0xFFC00000
#define DIRECTORY_PRESENT_BIT (0)
#define DIRECTORY_RW_BIT (1)
#define DIRECTORY_US_BIT (2)
#define DIRECTORY_WT_BIT (3)
#define DIRECTORY_CACHE_BIT (4)
#define DIRECTORY_ACCESSED_BIT (5)
#define DIRECTORY_PAGE_SIZE_BIT (7)
#define DIRECTORY_ADDR_MASK 0xFFFFF000
#define DIRECTORY_PRESENT_MASK (1 << DIRECTORY_PRESENT_BIT)
#define DIRECTORY_RW_MASK (1 << DIRECTORY_RW_BIT)
#define DIRECTORY_US_MASK (1 << DIRECTORY_US_BIT)
#define DIRECTORY_WT_MASK (1 << DIRECTORY_WT_BIT)
#define DIRECTORY_CACHE_MASK (1 << DIRECTORY_CACHE_BIT)
#define DIRECTORY_ACCESSED_MASK (1 << DIRECTORY_ACCESSED_BIT)
#define DIRECTORY_PAGE_SIZE_MASK (1 << DIRECTORY_PAGE_SIZE_BIT)
#define DIRECTORY_SIZE 1024
#define PAGING_MODE_4M (1 << 0)
#define PAGING_MODE_RW (1 << 1)
#define PAGING_MODE_US (1 << 2)
#define PAGING_RESULT_OK 0
#define PAGING_RESULT_INUSE 1
#define PAGING_RESULT_ALIGN 2
#define PAGING_RESULT_ERR 99
typedef uint32_t page_directory_entry;
typedef uint32_t page_table_entry;
#endif //NEW_KERNEL_PAGING_H

10
include/myke/mem/vmm.h Normal file
View File

@@ -0,0 +1,10 @@
//
// Created by rick on 17-10-21.
//
#ifndef NEW_KERNEL_VMM_H
#define NEW_KERNEL_VMM_H
void vmm_init(multiboot_info_t *multiboot_info);
#endif //NEW_KERNEL_VMM_H

View File

@@ -19,15 +19,15 @@ void task_start_first();
void task_switch_next();
uint32_t task_spawn(task_entrypoint, void *entry_data);
pid_t task_spawn(task_entrypoint, void *entry_data, char *name);
void task_end(uint32_t tid);
void task_end(pid_t tid);
void task_suspend();
uint32_t task_get_current_tid();
pid_t task_get_current_tid();
void task_signal(uint32_t tid);
void task_signal(pid_t tid);
void task_lock_acquire();
@@ -35,4 +35,6 @@ void task_ensure_enabled();
void task_lock_free();
void task_print_all();
#endif //NEW_KERNEL_TASK_H

30
include/myke/util/init.h Normal file
View File

@@ -0,0 +1,30 @@
//
// Created by rick on 13-08-21.
//
#ifndef NEW_KERNEL_INIT_H
#define NEW_KERNEL_INIT_H
#include <sys/types.h>
#include <myke/driver.h>
enum init_stage {
INIT_STAGE_EARLY_BOOT_0, // id mapped, high memory, no malloc
INIT_STAGE_EARLY_BOOT_1, // memory available, no tasking
INIT_STAGE_LATE_BOOT, // time source, memory, most basic hardware available
INIT_STAGE_PRE_TASKING, // just before tasking is ready
INIT_STAGE_AFTER_BOOT_PRE_INIT, // tasking just started
// todo define later stages
};
struct init {
const char *name;
enum init_stage stage;
void (*init)();
};
#define INIT_FUNCTION(order) GENERIC_DRIVER(init, order)
void init_execute_all(enum init_stage stage);
#endif //NEW_KERNEL_INIT_H

View File

@@ -0,0 +1,10 @@
//
// Created by rick on 26-03-21.
//
#ifndef NEW_KERNEL_SLINGURL_H
#define NEW_KERNEL_SLINGURL_H
void slingurl_decompose(const char* url);
#endif //NEW_KERNEL_SLINGURL_H

View File

@@ -9,6 +9,8 @@
#include <sys/types.h>
#include <myke/driver.h>
#define BLOCK_DEV_LBA_SIZE 512
#define BLOCK_DEV_ACCESS_OK 0
#define BLOCK_DEV_ACCESS_ERR 1
@@ -27,21 +29,21 @@
typedef struct block_device block_device_t;
typedef uint8_t (*block_device_driver_check_device)(const block_device_t *device, uint8_t *first_sector);
typedef uint8_t (*block_device_driver_check_device)(block_device_t *device);
typedef uint8_t (*block_device_driver_free)(const block_device_t *device);
typedef uint8_t (*block_device_driver_free)(block_device_t *device);
typedef uint8_t (*block_device_access)(const block_device_t *device, uint8_t direction, uint32_t lba, uint8_t sectors,
void *target);
struct block_dev_driver {
typedef struct block_dev_driver {
char name[16];
struct {
uint8_t partitioning: 1;
} flags;
block_device_driver_check_device check_device;
block_device_driver_free free_device;
} __attribute__((__aligned__(STRUCT_ALIGNMENT)));
} __attribute__((__aligned__(STRUCT_ALIGNMENT))) block_dev_driver_t;
#define BLOCK_DEV_DRIVER(order) GENERIC_DRIVER(block_dev_driver, order)
@@ -59,6 +61,7 @@ struct block_device {
block_device_access access;
struct block_dev_driver *driver;
void *device_info; // pointer to driver defined structure
void *driver_info; // pointer to driver defined structure
// todo device info
};
@@ -66,10 +69,8 @@ uint8_t block_dev_register(block_device_t *device);
void block_dev_free(block_device_t *device);
void block_dev_start_task();
void *block_dev_mount(const char *device, const char *driver_name);
void block_dev_print_info();
bool block_dev_mount(char *identifier, char *driver);
#endif //NEW_KERNEL_BLOCKDEV_H

223
include/myke/vfs/lfs/ext2.h Normal file
View File

@@ -0,0 +1,223 @@
//
// Created by rick on 18-09-21.
//
#ifndef NEW_KERNEL_EXT2_H
#define NEW_KERNEL_EXT2_H
#include <sys/types.h>
#include <attributes.h>
#define EXT2_SIGNATURE 0xEF53
#define EXT2_SB_ADDR 1024
#define EXT2_SB_SIZE 1024
#define EXT2_BGD_START_ADDR (EXT2_SB_ADDR + EXT2_SB_SIZE)
#define EXT2_DEFAULT_RESERVED_INODES 11
#define EXT2_DEFAULT_INODE_SIZE 128
#define EXT2_ROOT_INODE 2
typedef struct ext2_sb {
uint32_t total_inodes;
uint32_t total_blocks;
uint32_t num_reserved_su;
uint32_t unallocated_blocks;
uint32_t unallocated_inodes;
uint32_t no_blocks_with_sb;
uint32_t block_size;
uint32_t fragment_size;
uint32_t no_blocks_per_group;
uint32_t no_fragments_per_group;
uint32_t no_inodes_per_group;
uint32_t last_mounted;
uint32_t last_written;
uint16_t no_mounted_since_fschk;
uint16_t max_no_mounted_since_fschk;
uint16_t ext2_signature;
uint16_t fs_state;
uint16_t error_action;
uint16_t minor_version;
uint32_t last_fschk;
uint32_t interval_fschk;
uint32_t os_id;
uint32_t major_version;
uint16_t uid_reserved;
uint16_t gid_reserved;
// below extended fields
uint32_t first_nor_reserved_inode;
uint16_t size_inode;
uint16_t owner_bg;
uint32_t features_optional;
uint32_t features_required;
uint32_t features_ro;
uint8_t fs_id[16];
char fs_name[16];
char last_mounted_path[64];
uint32_t compression_alg;
uint8_t preallocate_files;
uint8_t preallocate_dirs;
uint16_t: 16; // unused
uint8_t journal_id[16];
uint32_t journal_inode;
uint32_t journal_device;
uint32_t head_of_orphan_inode_list;
} att_packed ext2_sb_t;
enum {
EXT2_FS_STATE_CLEAN = 1,
EXT2_FS_STATE_ERROR = 2,
};
enum {
EXT2_ERROR_ACTION_IGNORE = 1,
EXT2_ERROR_ACTION_REMOUNT_RO = 2,
EXT2_ERROR_ACTION_PANIC = 3,
};
enum {
EXT2_OS_ID_LINUX = 0,
EXT2_OS_ID_GNU_HURD = 1,
EXT2_OS_ID_MASIX = 2,
EXT2_OS_ID_FREE_BSD = 3,
EXT2_OS_ID_LITES = 4,
};
enum {
EXT2_FEATURE_OPTIONAL_PREALLOCATE = 0x01,
EXT2_FEATURE_OPTIONAL_AFS_SERVER_INODE = 0x02,
EXT2_FEATURE_OPTIONAL_HAS_JOURNAL = 0x04,
EXT2_FEATURE_OPTIONAL_EXTENDED_ATTRIBUTES = 0x08,
EXT2_FEATURE_OPTIONAL_CAN_RESIZE = 0x10,
EXT2_FEATURE_OPTIONAL_DIR_HASH_INDEX = 0x20,
};
#define EXT2_FEAT_OPT_SUPPORTED ( \
0 \
)
enum {
EXT2_FEATURE_REQUIRED_COMPRESSION = 0x01,
EXT2_FEATURE_REQUIRED_DIR_HAS_TYPE = 0x02,
EXT2_FEATURE_REQUIRED_JOURNAL_REPLAY_REQUIRED = 0x04,
EXT2_FEATURE_REQUIRED_HAS_JOURNAL_DEVICE = 0x08,
};
#define EXT2_FEAT_REQ_SUPPORTED ( \
EXT2_FEATURE_REQUIRED_DIR_HAS_TYPE | \
0 \
)
enum {
EXT2_FEATURE_RO_SPARSE_SUPERBLOCKS_AND_GROUPS_DESCRIPTOR = 0x01,
EXT2_FEATURE_RO_64BIT_SIZE = 0x02,
EXT2_FEATURE_RO_DIR_BTREE = 0X04
};
#define EXT2_FEAT_RO_64BIT_SIZE (SIZE_MAX > UINT32_MAX)
#define EXT2_FEAT_RO_SUPPORTED ( \
(EXT2_FEAT_RO_64BIT_SIZE ? EXT2_FEATURE_RO_64BIT_SIZE : 0) | \
0 \
)
typedef struct ext2_bg_descriptor {
uint32_t block_usage_bm;
uint32_t inode_usage_bm;
uint32_t start_block_inode;
uint16_t no_unallocated_blocks;
uint16_t no_unallocated_inodes;
uint16_t no_dirs;
uint8_t unused[14];
} ext2_bg_descriptor_t;
typedef struct ext2_inode {
union {
uint16_t type_permission;
struct {
uint8_t permission_o: 3;
uint8_t permission_g: 3;
uint8_t permission_u: 3;
bool permission_sticky: 1;
bool permission_setgid: 1;
bool permission_setuid: 1;
uint8_t type: 4;
} att_packed;
};
uint16_t uid;
uint32_t size_l;
uint32_t last_access;
uint32_t created;
uint32_t last_mod;
uint32_t deleted;
uint16_t gid;
uint16_t no_hard_links;
uint32_t no_sectors;
uint32_t flags;
uint32_t os_val1;
uint32_t dbp[12]; // fist 12 direct block pointers
uint32_t sibp;
uint32_t dibp;
uint32_t tibp;
uint32_t generation;
uint32_t extended_attr;
union {
uint32_t size_h;
uint32_t dir_acl;
};
uint32_t fragment_addr;
uint8_t os_val2[12];
} att_packed ext2_inode_t;
enum {
EXT2_INODE_FLAG_SECURE_DELETE = 0x00000001,
EXT2_INODE_FLAG_KEEP_COPY_ON_DELETE = 0x00000002,
EXT2_INODE_FLAG_FILE_COMPRESSION = 0x00000004,
EXT2_INODE_FLAG_SYNC_UPDATE = 0x00000008,
EXT2_INODE_FLAG_IMMUTABLE = 0x00000010,
EXT2_INODE_FLAG_APPEND_ONLY = 0x00000020,
EXT2_INODE_FLAG_NO_DUMP = 0x00000040,
EXT2_INODE_FLAG_LAST_ACCESS_IGNORE = 0x00000080,
EXT2_INODE_FLAG_HASH_INDEXED_DIR = 0x00010000,
EXT2_INODE_FLAG_AFS_DIRECTORY = 0x00020000,
EXT2_INODE_FLAG_JOURNAL_FILE_DATA = 0x00040000,
};
typedef struct ext2_dir_entry {
uint32_t inode;
uint16_t ent_size;
uint8_t name_size;
uint8_t type_or_name_size_h;
char name;
} ext2_dir_entry_t;
enum {
EXT2_INODE_TYPE_FIFO = 0x1,
EXT2_INODE_TYPE_CHAR_DEV = 0x2,
EXT2_INODE_TYPE_DIR = 0x4,
EXT2_INODE_TYPE_BLOCK_DEV = 0x6,
EXT2_INODE_TYPE_FILE = 0x8,
EXT2_INODE_TYPE_SYM_LINK = 0xA,
EXT2_INODE_TYPE_UNIX_SOCK = 0xC,
};
enum {
EXT2_DIR_TYPE_UNKNOWN = 0,
EXT2_DIR_TYPE_FILE = 1,
EXT2_DIR_TYPE_DIR = 2,
EXT2_DIR_TYPE_CHAR_DEV = 3,
EXT2_DIR_TYPE_BLOCK_DEV = 4,
EXT2_DIR_TYPE_FIFO = 5,
EXT2_DIR_TYPE_SOCKET = 6,
EXT2_DIR_TYPE_SOFT_LINK = 7,
};
typedef struct ext2_mount_info {
ext2_sb_t sb;
uint32_t no_block_groups;
uint64_t block_size;
uint64_t fragment_size;
void *block_dev;
} ext2_mount_info_t;
#endif //NEW_KERNEL_EXT2_H

View File

@@ -0,0 +1,36 @@
//
// Created by rick on 19-09-21.
//
#ifndef NEW_KERNEL_VFS_DRIVER_H
#define NEW_KERNEL_VFS_DRIVER_H
#include <myke/driver.h>
#include <myke/vfs/vfs.h>
typedef struct vfs_driver {
char name[16];
struct {
} flags;
// api
int (*vfs_mount)(vfs_mount_t *mount);
int (*open)(vfs_mount_t *mount, vfs_fd_t *dir, const char *path, int mode, vfs_fd_t *out);
int (*close)(vfs_mount_t *mount, vfs_fd_t *fd);
int (*fstat)(vfs_mount_t *mount, vfs_fd_t *fd, stat_t *target, int flags);
int (*fread)(vfs_mount_t *mount, vfs_fd_t *fd, void *target, size_t size);
int (*dgetent)(vfs_mount_t *mount, vfs_fd_t *fd, void *target, size_t size);
} __attribute__((__aligned__(STRUCT_ALIGNMENT))) vfs_driver_t;
void vfs_mk_dirent_record(vfs_dirent_t *ent, uint32_t inode, uint32_t cur_offset, uint8_t type, char *name,
size_t name_length);
#define VFS_DRIVER(order) GENERIC_DRIVER(vfs_driver, order)
#endif //NEW_KERNEL_VFS_DRIVER_H

70
include/myke/vfs/vfs.h Normal file
View File

@@ -0,0 +1,70 @@
//
// Created by rick on 19-09-21.
//
#ifndef NEW_KERNEL_VFS_H
#define NEW_KERNEL_VFS_H
#include <stdbool.h>
#include <sys/stat.h>
#define VFS_MOUNT_OK 0
#define VFS_MOUNT_ERROR 1
#define VFS_OPEN_ERROR 1
#define VFS_OPEN_OK 0
#define VFS_CLOSE_OK 1
#define VFS_READ_ERROR (-1)
#define VFS_DGETENTS_ERR 1
struct vfs_mount;
typedef struct vfs_mount {
struct {
} flags;
const char *prefix;
const char *device;
void *driver; // vfs_mount_driver_t
void *global_driver_data;
struct vfs_mount *next;
} vfs_mount_t;
typedef struct vfs_fd {
struct {
} flags;
vfs_mount_t *mount;
void *driver_data;
} vfs_fd_t;
#define VFS_DIRENT_BASE_SIZE (4 + 4 + 2 + 1)
#define VFS_DIRENT_SIZE(name_length) ((VFS_DIRENT_BASE_SIZE + (name_length) + 1 + 15) & (~0xF))
#define VFS_DIRENT_MAX_SIZE (VFS_DIRENT_BASE_SIZE + 256 + 1)
typedef struct vfs_dirent {
uint32_t inode;
uint32_t offset_next;
uint16_t reclen;
uint8_t type;
char name[];
} vfs_dirent_t;
int vfs_mount(const char *path, const char *device, const char *driver);
// https://man7.org/linux/man-pages/man2/open.2.html
vfs_fd_t *vfs_open(const char *path, int flags, int mode);
void vfs_close(vfs_fd_t *fd);
// https://man7.org/linux/man-pages/man2/stat.2.html
int vfs_fstat(vfs_fd_t *fd, stat_t *target, int flags);
// https://man7.org/linux/man-pages/man2/read.2.html
int vfs_read(vfs_fd_t *fd, void *target, size_t size);
// inspiration https://man7.org/linux/man-pages/man2/getdents.2.html
int vfs_getdents(vfs_fd_t *fd, void *target, int count);
#endif //NEW_KERNEL_VFS_H

View File

@@ -1,460 +0,0 @@
/******************************************************************************
*
* Name: acenv.h - Host and compiler configuration
*
*****************************************************************************/
/******************************************************************************
*
* 1. Copyright Notice
*
* Some or all of this work - Copyright (c) 1999 - 2021, Intel Corp.
* All rights reserved.
*
* 2. License
*
* 2.1. This is your license from Intel Corp. under its intellectual property
* rights. You may have additional license terms from the party that provided
* you this software, covering your right to use that party's intellectual
* property rights.
*
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
* copy of the source code appearing in this file ("Covered Code") an
* irrevocable, perpetual, worldwide license under Intel's copyrights in the
* base code distributed originally by Intel ("Original Intel Code") to copy,
* make derivatives, distribute, use and display any portion of the Covered
* Code in any form, with the right to sublicense such rights; and
*
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
* license (with the right to sublicense), under only those claims of Intel
* patents that are infringed by the Original Intel Code, to make, use, sell,
* offer to sell, and import the Covered Code and derivative works thereof
* solely to the minimum extent necessary to exercise the above copyright
* license, and in no event shall the patent license extend to any additions
* to or modifications of the Original Intel Code. No other license or right
* is granted directly or by implication, estoppel or otherwise;
*
* The above copyright and patent license is granted only if the following
* conditions are met:
*
* 3. Conditions
*
* 3.1. Redistribution of Source with Rights to Further Distribute Source.
* Redistribution of source code of any substantial portion of the Covered
* Code or modification with rights to further distribute source must include
* the above Copyright Notice, the above License, this list of Conditions,
* and the following Disclaimer and Export Compliance provision. In addition,
* Licensee must cause all Covered Code to which Licensee contributes to
* contain a file documenting the changes Licensee made to create that Covered
* Code and the date of any change. Licensee must include in that file the
* documentation of any changes made by any predecessor Licensee. Licensee
* must include a prominent statement that the modification is derived,
* directly or indirectly, from Original Intel Code.
*
* 3.2. Redistribution of Source with no Rights to Further Distribute Source.
* Redistribution of source code of any substantial portion of the Covered
* Code or modification without rights to further distribute source must
* include the following Disclaimer and Export Compliance provision in the
* documentation and/or other materials provided with distribution. In
* addition, Licensee may not authorize further sublicense of source of any
* portion of the Covered Code, and must include terms to the effect that the
* license from Licensee to its licensee is limited to the intellectual
* property embodied in the software Licensee provides to its licensee, and
* not to intellectual property embodied in modifications its licensee may
* make.
*
* 3.3. Redistribution of Executable. Redistribution in executable form of any
* substantial portion of the Covered Code or modification must reproduce the
* above Copyright Notice, and the following Disclaimer and Export Compliance
* provision in the documentation and/or other materials provided with the
* distribution.
*
* 3.4. Intel retains all right, title, and interest in and to the Original
* Intel Code.
*
* 3.5. Neither the name Intel nor any other trademark owned or controlled by
* Intel shall be used in advertising or otherwise to promote the sale, use or
* other dealings in products derived from or relating to the Covered Code
* without prior written authorization from Intel.
*
* 4. Disclaimer and Export Compliance
*
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
* LIMITED REMEDY.
*
* 4.3. Licensee shall not export, either directly or indirectly, any of this
* software or system incorporating such software without first obtaining any
* required license or other approval from the U. S. Department of Commerce or
* any other agency or department of the United States Government. In the
* event Licensee exports any such software from the United States or
* re-exports any such software from a foreign destination, Licensee shall
* ensure that the distribution and export/re-export of the software is in
* compliance with all laws, regulations, orders, or other restrictions of the
* U.S. Export Administration Regulations. Licensee agrees that neither it nor
* any of its subsidiaries will export/re-export any technical data, process,
* software, or service, directly or indirectly, to any country for which the
* United States government or any agency thereof requires an export license,
* other governmental approval, or letter of assurance, without first obtaining
* such license, approval or letter.
*
*****************************************************************************
*
* Alternatively, you may choose to be licensed under the terms of the
* following license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, you may choose to be licensed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
*****************************************************************************/
#ifndef __ACENV_H__
#define __ACENV_H__
/*
* Environment configuration. The purpose of this file is to interface ACPICA
* to the local environment. This includes compiler-specific, OS-specific,
* and machine-specific configuration.
*/
/* Types for ACPI_MUTEX_TYPE */
#define ACPI_BINARY_SEMAPHORE 0
#define ACPI_OSL_MUTEX 1
/* Types for DEBUGGER_THREADING */
#define DEBUGGER_SINGLE_THREADED 0
#define DEBUGGER_MULTI_THREADED 1
/******************************************************************************
*
* Configuration for ACPI tools and utilities
*
*****************************************************************************/
/* Common application configuration. All single threaded except for AcpiExec. */
#if (defined ACPI_ASL_COMPILER) || \
(defined ACPI_BIN_APP) || \
(defined ACPI_DUMP_APP) || \
(defined ACPI_HELP_APP) || \
(defined ACPI_NAMES_APP) || \
(defined ACPI_SRC_APP) || \
(defined ACPI_XTRACT_APP) || \
(defined ACPI_EXAMPLE_APP) || \
(defined ACPI_EFI_HELLO)
#define ACPI_APPLICATION
#define ACPI_SINGLE_THREADED
#define USE_NATIVE_ALLOCATE_ZEROED
#endif
/* iASL configuration */
#ifdef ACPI_ASL_COMPILER
#define ACPI_DEBUG_OUTPUT
#define ACPI_CONSTANT_EVAL_ONLY
#define ACPI_LARGE_NAMESPACE_NODE
#define ACPI_DATA_TABLE_DISASSEMBLY
#define ACPI_32BIT_PHYSICAL_ADDRESS
#define ACPI_DISASSEMBLER 1
#endif
/* AcpiExec configuration. Multithreaded with full AML debugger */
#ifdef ACPI_EXEC_APP
#define ACPI_APPLICATION
#define ACPI_FULL_DEBUG
#define ACPI_MUTEX_DEBUG
#define ACPI_DBG_TRACK_ALLOCATIONS
#endif
/* AcpiHelp configuration. Error messages disabled. */
#ifdef ACPI_HELP_APP
#define ACPI_NO_ERROR_MESSAGES
#endif
/* AcpiNames configuration. Debug output enabled. */
#ifdef ACPI_NAMES_APP
#define ACPI_DEBUG_OUTPUT
#endif
/* AcpiExec/AcpiNames/Example configuration. Native RSDP used. */
#if (defined ACPI_EXEC_APP) || \
(defined ACPI_EXAMPLE_APP) || \
(defined ACPI_NAMES_APP)
#define ACPI_USE_NATIVE_RSDP_POINTER
#endif
/* AcpiDump configuration. Native mapping used if provided by the host */
#ifdef ACPI_DUMP_APP
#define ACPI_USE_NATIVE_MEMORY_MAPPING
#endif
/* AcpiNames/Example configuration. Hardware disabled */
#if (defined ACPI_EXAMPLE_APP) || \
(defined ACPI_NAMES_APP)
#define ACPI_REDUCED_HARDWARE 1
#endif
/* Linkable ACPICA library. Two versions, one with full debug. */
#ifdef ACPI_LIBRARY
#define ACPI_USE_LOCAL_CACHE
#define ACPI_DEBUGGER 1
#define ACPI_DISASSEMBLER 1
#ifdef _DEBUG
#define ACPI_DEBUG_OUTPUT
#endif
#endif
/* Common for all ACPICA applications */
#ifdef ACPI_APPLICATION
#define ACPI_USE_LOCAL_CACHE
#endif
/* Common debug/disassembler support */
#ifdef ACPI_FULL_DEBUG
#define ACPI_DEBUG_OUTPUT
#define ACPI_DEBUGGER 1
#define ACPI_DISASSEMBLER 1
#endif
/*
* acpisrc CR\LF support
* Unix file line endings do not include the carriage return.
* If the acpisrc utility is being built using a microsoft compiler, it means
* that it will be running on a windows machine which means that the output is
* expected to have CR/LF newlines. If the acpisrc utility is built with
* anything else, it will likely run on a system with LF newlines. This flag
* tells the acpisrc utility that newlines will be in the LF format.
*/
#if defined(ACPI_SRC_APP) && !defined(_MSC_VER)
#define ACPI_SRC_OS_LF_ONLY 1
#else
#define ACPI_SRC_OS_LF_ONLY 0
#endif
/*! [Begin] no source code translation */
/******************************************************************************
*
* Host configuration files. The compiler configuration files are included
* first.
*
*****************************************************************************/
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
#include <platform/acgcc.h>
#elif defined(_MSC_VER)
#include "acmsvc.h"
#elif defined(__INTEL_COMPILER)
#include "acintel.h"
#endif
// Override include env behavior
#include <acmyke.h>
/*! [End] no source code translation !*/
/******************************************************************************
*
* Setup defaults for the required symbols that were not defined in one of
* the host/compiler files above.
*
*****************************************************************************/
/* 64-bit data types */
#ifndef COMPILER_DEPENDENT_INT64
#define COMPILER_DEPENDENT_INT64 long long
#endif
#ifndef COMPILER_DEPENDENT_UINT64
#define COMPILER_DEPENDENT_UINT64 unsigned long long
#endif
/* Type of mutex supported by host. Default is binary semaphores. */
#ifndef ACPI_MUTEX_TYPE
#define ACPI_MUTEX_TYPE ACPI_BINARY_SEMAPHORE
#endif
/* Global Lock acquire/release */
#ifndef ACPI_ACQUIRE_GLOBAL_LOCK
#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acquired) Acquired = 1
#endif
#ifndef ACPI_RELEASE_GLOBAL_LOCK
#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Pending) Pending = 0
#endif
/* Flush CPU cache - used when going to sleep. Wbinvd or similar. */
#ifndef ACPI_FLUSH_CPU_CACHE
#define ACPI_FLUSH_CPU_CACHE()
#endif
/* "inline" keywords - configurable since inline is not standardized */
#ifndef ACPI_INLINE
#define ACPI_INLINE
#endif
/* Use ordered initialization if compiler doesn't support designated. */
#ifndef ACPI_STRUCT_INIT
#define ACPI_STRUCT_INIT(field, value) value
#endif
/*
* Configurable calling conventions:
*
* ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads)
* ACPI_EXTERNAL_XFACE - External ACPI interfaces
* ACPI_INTERNAL_XFACE - Internal ACPI interfaces
* ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces
*/
#ifndef ACPI_SYSTEM_XFACE
#define ACPI_SYSTEM_XFACE
#endif
#ifndef ACPI_EXTERNAL_XFACE
#define ACPI_EXTERNAL_XFACE
#endif
#ifndef ACPI_INTERNAL_XFACE
#define ACPI_INTERNAL_XFACE
#endif
#ifndef ACPI_INTERNAL_VAR_XFACE
#define ACPI_INTERNAL_VAR_XFACE
#endif
/*
* Debugger threading model
* Use single threaded if the entire subsystem is contained in an application
* Use multiple threaded when the subsystem is running in the kernel.
*
* By default the model is single threaded if ACPI_APPLICATION is set,
* multi-threaded if ACPI_APPLICATION is not set.
*/
#ifndef DEBUGGER_THREADING
#if !defined (ACPI_APPLICATION) || defined (ACPI_EXEC_APP)
#define DEBUGGER_THREADING DEBUGGER_MULTI_THREADED
#else
#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED
#endif
#endif /* !DEBUGGER_THREADING */
/******************************************************************************
*
* C library configuration
*
*****************************************************************************/
/*
* ACPI_USE_SYSTEM_CLIBRARY - Define this if linking to an actual C library.
* Otherwise, local versions of string/memory functions will be used.
* ACPI_USE_STANDARD_HEADERS - Define this if linking to a C library and
* the standard header files may be used. Defining this implies that
* ACPI_USE_SYSTEM_CLIBRARY has been defined.
*
* The ACPICA subsystem only uses low level C library functions that do not
* call operating system services and may therefore be inlined in the code.
*
* It may be necessary to tailor these include files to the target
* generation environment.
*/
/* Use the standard C library headers. We want to keep these to a minimum. */
#ifdef ACPI_USE_STANDARD_HEADERS
/* Use the standard headers from the standard locations */
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#if defined (ACPI_APPLICATION) || defined(ACPI_LIBRARY)
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#endif
#endif /* ACPI_USE_STANDARD_HEADERS */
#ifdef ACPI_APPLICATION
#define ACPI_FILE FILE *
#define ACPI_FILE_OUT stdout
#define ACPI_FILE_ERR stderr
#else
#define ACPI_FILE void *
#define ACPI_FILE_OUT NULL
#define ACPI_FILE_ERR NULL
#endif /* ACPI_APPLICATION */
#ifndef ACPI_INIT_FUNCTION
#define ACPI_INIT_FUNCTION
#endif
#endif /* __ACENV_H__ */

View File

@@ -24,7 +24,7 @@ void fflush(FILE *);
FILE *fopen(const char *, const char *);
void fprintf(FILE *, const char *, ...);
void __attribute__((format (printf, 2, 3))) fprintf(FILE *, const char *, ...);
size_t fread(void *, size_t, size_t, FILE *);
@@ -38,11 +38,11 @@ void setbuf(FILE *, char *);
int vfprintf(FILE *, const char *, va_list);
int vprintf(const char* fmt, va_list args);
int vprintf(const char *fmt, va_list args);
int printf(const char *fmt, ...);
int __attribute__((format (printf, 1, 2))) printf(const char *fmt, ...);
int sprintf(char *target, const char *fmt, ...);
int __attribute__((format (printf, 2, 3))) sprintf(char *target, const char *fmt, ...);
#endif //NEW_KERNEL_STDIO_H

View File

@@ -21,7 +21,7 @@ int atexit(void (*)(void));
int atoi(const char *);
char *itoa(int value, char *buffer, int base);
char *itoa(uint32_t value, char *buffer, int base);
char *getenv(const char *);

View File

@@ -7,23 +7,31 @@
#include <stddef.h>
int memcpy(void *dst, const void *src, size_t amount);
void *memcpy(void *dst, const void *src, size_t amount);
int memset(void *dst, int data, size_t amount);
void *memset(void *dst, int data, size_t amount);
int strcpy(char *dst, const char *src);
void *memmove(void *dst, const void *src, size_t amount);
int strncpy(char *dst, const char *src, size_t n);
void *strcpy(char *dst, const char *src);
void *strncpy(char *dst, const char *src, size_t n);
size_t strlen(const char *str);
const char *strchr(const char *s, char c);
char *strchr(const char *s, char c);
char *strrchr(const char *s, char c);
int memcmp(const void *s1, const void *s2, size_t n);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, int n);
int strncmp(const char *s1, const char *s2, size_t n);
char *strdup(const char *s);
char *strndup(const char *s, size_t n);
char *strcat(char *dest, const char *src);

View File

@@ -7,5 +7,6 @@
#define MIN(a, b) (((a)<(b))?(a):(b))
#define MAX(a, b) (((a)>(b))?(a):(b))
#define DIV_ROUND_UP(a, b) (((a) + ((b) - 1)) / (b))
#endif //NEW_KERNEL_PARAM_H

50
include/sys/stat.h Normal file
View File

@@ -0,0 +1,50 @@
//
// Created by rick on 06-10-21.
//
#ifndef NEW_KERNEL_STAT_H
#define NEW_KERNEL_STAT_H
#include <time.h>
// https://man7.org/linux/man-pages/man2/stat.2.html
typedef uint32_t dev_t;
typedef uint32_t ino_t;
typedef uint32_t mode_t;
typedef uint32_t nlink_t;
typedef uint32_t uid_t;
typedef uint32_t gid_t;
typedef size_t off_t;
typedef size_t blksize_t;
typedef uint32_t blkcnt_t;
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
nlink_t st_nlink; /* Number of hard links */
uid_t st_uid; /* User ID of owner */
gid_t st_gid; /* Group ID of owner */
dev_t st_rdev; /* Device ID (if special file) */
off_t st_size; /* Total size, in bytes */
blksize_t st_blksize; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* Time of last access */
struct timespec st_mtim; /* Time of last modification */
struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
typedef struct stat stat_t;
#endif //NEW_KERNEL_STAT_H

View File

@@ -5,4 +5,10 @@
#ifndef NEW_KERNEL_TIME_H
#define NEW_KERNEL_TIME_H
typedef uint32_t time_t;
struct timespec {
time_t tv_sec;
long tv_nsec;
};
#endif //NEW_KERNEL_TIME_H

284
kernel/acpi/acpi.c Normal file
View File

@@ -0,0 +1,284 @@
//
// Created by rick on 22-08-21.
//
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <lai/core.h>
#include <lai/helpers/pc-bios.h>
#include <myke/acpi/acpi.h>
#include <myke/acpi/structures.h>
#include <myke/cpu/lapic.h>
#include <myke/libk/libk.h>
#include <myke/util/init.h>
void acpi_handle_facp(const struct acpi_sdt_header *addr);
void acpi_handle_apic(const struct acpi_sdt_header *addr);
struct acpi_type acpi_types[] = {
{"APIC", "Multiple APIC Description Table (MADT)", acpi_handle_apic},
{"BGRT", "Boot Graphics Resource Table (BGRT; only supported on UEFI systems)", NULL},
{"BERT", "Boot Error Record Table (BERT)", NULL},
{"CPEP", "Corrected Platform Error Polling Table (CPEP)", NULL},
{"DSDT", "Differentiated System Description Table (DSDT)", NULL},
{"ECDT", "Embedded Controller Boot Resources Table (ECDT)", NULL},
{"EINJ", "Error Injection Table (EINJ)", NULL},
{"ERST", "Error Record Serialization Table (ERST)", NULL},
{"FACP", "Fixed ACPI Description Table (FADT)", acpi_handle_facp},
{"FACS", "Firmware ACPPI Control Structure (FACS)", NULL},
{"HEST", "Hardware Error Source Table (HEST)", NULL},
{"MSCT", "Maximum System Characteristics Table (MSCT)", NULL},
{"MPST", "Memory Power State Table (MPST)", NULL},
// {"OEMx", "OEM Specific Information Tables (Any table with a signature beginning with \"OEM\" falls into this definition)", NULL},
{"PMTT", "latform Memory Topology Table (PMTT)", NULL},
{"PSDT", "Persistent System Description Table (PSDT)", NULL},
{"RASF", "ACPI RAS FeatureTable (RASF)", NULL},
{"RSDT", "Root System Description Table (RSDT; 32-bit version of the XSDT)", NULL},
{"SBST", "Smart Battery Specification Table (SBST)", NULL},
{"SLIT", "System Locality System Information Table (SLIT)", NULL},
{"SRAT", "System Resource Affinity Table (SRAT)", NULL},
{"SSDT", "Secondary System Description Table (SSDT)", NULL},
{"XSDT", "Extended System Description Table (This wiki page; included for completeness)", NULL},
{"\0\0\0\0", NULL, NULL},
};
bool acpi_checksum(const void *table_addr, const size_t table_size) {
if (table_size < 1) {
return false; // invalid input
}
const uint8_t *table = table_addr;
uint8_t val = 0;
for (size_t i = 0; i < table_size; ++i) {
val += table[i];
}
return val == 0;
}
const struct acpi_rsdt *rsdt_table = NULL;
const struct acpi_xsdt *xsdt_table = NULL;
const struct acpi_fadt_t *fadt;
const struct acpi_sdt_header *dsdt;
void acpi_handle_facp(const struct acpi_sdt_header *addr) {
// parse the FACP/FADT
fadt = (const struct acpi_fadt_t *) addr;
if (fadt->header.revision > 5) {
// minor since 5.1
printf("ACPI Revision: %i.%i %.6s\n", fadt->header.revision, fadt->minor_version, fadt->header.oem);
} else {
printf("ACPI Revision: %i.0 %.6s\n", fadt->header.revision, fadt->header.oem);
}
if (fadt->x_dsdt != 0 && fadt->x_dsdt < UINT32_MAX) {
dsdt = (struct acpi_sdt_header *) fadt->x_dsdt;
} else if (fadt->dsdt != 0) {
dsdt = (struct acpi_sdt_header *) fadt->dsdt;
} else {
k_panics("No DSDT");
}
if (!acpi_checksum(dsdt, dsdt->length)) {
k_panics("DSDT is not valid");
}
}
void acpi_handle_apic(const struct acpi_sdt_header *addr) {
const struct acpi_madt *madt = (const struct acpi_madt *) addr;
printf("Local apic: %p %i\n", madt->local_apic_addr, madt->flags_int);
lapic_set_addr(madt->local_apic_addr);
const uint8_t *current = madt->entries;
const uint8_t *end = (const uint8_t *) (madt) + madt->header.length;
while (current < end) {
struct acpi_madt_entry_header *current_header = (struct acpi_madt_entry_header *) current;
switch (current_header->type) {
case MADT_TYPE_PROCESSOR_LOCAL_APIC: {
const struct acpi_madt_local_apic *la = (const struct acpi_madt_local_apic *) current_header;
printf("Local APIC %x for %x %x\n", la->apic_id, la->processor_id, la->flags);
break;
}
case MADT_TYPE_IO_APIC: {
const struct acpi_madt_io_apic *ia = (const struct acpi_madt_io_apic *) current_header;
printf("IO APIC %x at %x with %x\n", ia->apic_id, ia->io_apic_address,
ia->global_system_interrupt_base);
break;
}
case MADT_TYPE_IO_APIC_INTERRUPT_SOURCE_OVERRIDE: {
const struct acpi_madt_io_apic_interrupt_source_override *override = (const struct acpi_madt_io_apic_interrupt_source_override *) current_header;
printf("IO APIC Interrupt source override %x:%x -> %x %x\n", override->bus_source, override->irq_source,
override->global_system_interrupt, override->flags);
break;
}
case MADT_TYPE_IO_APIC_NON_MASKABLE_INTERRUPT_SOURCE: {
const struct acpi_madt_io_apic_non_maskable_interrupt *nmi = (const struct acpi_madt_io_apic_non_maskable_interrupt *) current_header;
printf("IO APIC NMI source %x %x %x\n", nmi->nmi_source, nmi->flags, nmi->global_system_interrupt);
break;
}
case MADT_TYPE_LOCAL_APIC_NON_MASKABLE_INTERRUPTS: {
const struct acpi_madt_local_apic_non_maskable_interrupts *nmi = (const struct acpi_madt_local_apic_non_maskable_interrupts *) current_header;
printf("Local APIC NMI CPU %x %x %x\n", nmi->acpi_processor_id, nmi->flags, nmi->lint_no);
break;
}
case MADT_TYPE_LOCAL_APIC_ADDRESS_OVERRIDE: {
const struct acpi_madt_local_apic_address_override *ao = (const struct acpi_madt_local_apic_address_override *) current_header;
printf("Local APIC addr override %x%x\n", ao->physical_address_local_apic >> 32,
ao->physical_address_local_apic & UINT32_MAX);
if (ao->physical_address_local_apic > UINT32_MAX) {
printf("Override above 4GB!");
} else {
lapic_set_addr(ao->physical_address_local_apic & UINT32_MAX);
}
break;
}
case MADT_TYPE_PROCESSOR_LOCAL_X2_APIC: {
const struct acpi_madt_processor_local_x2_apic *x2 = (const struct acpi_madt_processor_local_x2_apic *) current_header;
printf("Local x2APIC %x %x %x\n", x2->processors_local_x2_apic_id, x2->flags, x2->acpi_id);
break;
}
default:
printf("Unknown MADT entry %x", current_header->type);
break;
}
current += current_header->length;
}
printf("Lapic id %x v%x\n", lapic_get_id(), lapic_get_version());
}
void acpi_parse_table(uint32_t table_addr, uint32_t index) {
struct acpi_sdt_header *s_header = (struct acpi_sdt_header *) table_addr;
if (!acpi_checksum(s_header, s_header->length)) {
printf("%i: invalid acpi entry\n", index);
return;
}
struct acpi_type *c = &acpi_types[0];
while (c->name[0] != '\0') {
if (strncmp(s_header->signature, c->name, 4) == 0) {
printf("%i: %.4s %s\n", index, c->name, c->description);
if (c->handle_table != NULL) {
c->handle_table(s_header);
}
break;
}
c += 1;
}
if (c->name[0] == '\0') {
printf("%i: %.4s unknown\n", index, s_header->signature);
}
}
void acpi_parse_rsdt(uint32_t address) {
printf("Parsing RSDT\n");
rsdt_table = (const struct acpi_rsdt *) address;
if (!acpi_checksum(rsdt_table, rsdt_table->header.length)) {
k_panics("Malformed RSDT");
}
if (strncmp(rsdt_table->header.signature, "RSDT", 4) != 0) {
k_panics("RSDT pointer is not RSDT");
}
uint32_t entries = (rsdt_table->header.length - sizeof(struct acpi_sdt_header)) / sizeof(uint32_t);
for (uint32_t i = 0; i < entries; ++i) {
acpi_parse_table(rsdt_table->pointer_to_other_sdt[i], i);
}
}
void acpi_parse_xsdt(uint64_t address) {
printf("Parsing XSDT\n");
if (address > UINT32_MAX) {
k_panics("acpi table above 4GB");
}
xsdt_table = (const struct acpi_xsdt *) (uint32_t) address;
if (!acpi_checksum(xsdt_table, xsdt_table->header.length)) {
k_panics("Malformed XSDT");
}
if (strncmp(xsdt_table->header.signature, "XSDT", 4) != 0) {
k_panics("XSDT pointer is not XSDT");
}
uint32_t entries = (xsdt_table->header.length - sizeof(struct acpi_sdt_header)) / sizeof(uint64_t);
for (uint32_t i = 0; i < entries; ++i) {
const uint64_t entry_addr = xsdt_table->pointer_to_other_sdt[i];
if (entry_addr > UINT32_MAX) {
printf("%i: Above 4GB\n", i);
continue;
}
acpi_parse_table(xsdt_table->pointer_to_other_sdt[i], i);
}
}
void *acpi_find_table_by_name(const char *name, int skip) {
if (xsdt_table != NULL) {
uint32_t entries = (xsdt_table->header.length - sizeof(struct acpi_sdt_header)) / sizeof(uint64_t);
for (uint32_t i = 0; i < entries; ++i) {
const uint64_t entry_addr = xsdt_table->pointer_to_other_sdt[i];
if (entry_addr > UINT32_MAX) {
printf("%i: Above 4GB\n", i);
continue;
}
struct acpi_sdt_header *header = (struct acpi_sdt_header *) xsdt_table->pointer_to_other_sdt[i];
if (!acpi_checksum(header, header->length)) {
printf("Invalid header %d", i);
continue;
}
if (strncmp(header->signature, name, 4) == 0) {
if (skip > 0) {
skip--;
continue;
}
return header;
}
}
}
if (rsdt_table != NULL) {
uint32_t entries = (rsdt_table->header.length - sizeof(struct acpi_sdt_header)) / sizeof(uint32_t);
for (uint32_t i = 0; i < entries; ++i) {
struct acpi_sdt_header *header = (struct acpi_sdt_header *) rsdt_table->pointer_to_other_sdt[i];
if (!acpi_checksum(header, header->length)) {
printf("Invalid header %d", i);
continue;
}
if (strncmp(header->signature, name, 4) == 0) {
if (skip > 0) {
skip--;
continue;
}
return header;
}
}
}
// check if DSDT is requested, but was not present as normal table
if (strncmp(name, "DSDT", 4) == 0) {
return (void *) dsdt;
}
return NULL;
}
void acpi_parse() {
struct lai_rsdp_info lai_rsdp_info;
lai_api_error_t result = lai_bios_detect_rsdp(&lai_rsdp_info);
if (result != LAI_ERROR_NONE) {
printf("LAI: could not find rsdp: %s\n", lai_api_error_to_string(result));
k_panics("Could not init ACPI");
}
lai_set_acpi_revision(lai_rsdp_info.acpi_version);
if (lai_rsdp_info.xsdt_address != 0) {
acpi_parse_xsdt(lai_rsdp_info.xsdt_address);
} else if (lai_rsdp_info.rsdt_address != 0) {
acpi_parse_rsdt(lai_rsdp_info.rsdt_address);
} else {
k_panics("No rsdt nor xsdt");
}
}
void acpi_init() {
acpi_parse();
lai_create_namespace();
}
INIT_FUNCTION(100) = {
.name = "acpi",
.stage = INIT_STAGE_EARLY_BOOT_1,
.init = acpi_init,
};

View File

@@ -1,342 +0,0 @@
//
// Created by rick on 01-03-21.
//
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <acpi.h>
#include <myke/acpi.h>
#include <myke/tasks/task.h>
#include <myke/tasks/locking.h>
#include <myke/libk/libk.h>
ACPI_STATUS AcpiOsInitialize() {
return AE_OK;
}
ACPI_STATUS AcpiOsTerminate() {
return AE_OK;
}
ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer() {
ACPI_PHYSICAL_ADDRESS addr = 0;
AcpiFindRootPointer(&addr);
return addr;
}
ACPI_STATUS AcpiOsPredefinedOverride(const struct acpi_predefined_names *names, ACPI_STRING *newval) {
*newval = NULL;
return AE_OK;
}
ACPI_STATUS AcpiOsTableOverride(struct acpi_table_header *existingTable, struct acpi_table_header **newTable) {
*newTable = NULL;
return AE_OK;
}
void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS physicalAddress, ACPI_SIZE length) {
return ACPI_TO_POINTER(physicalAddress);
}
void AcpiOsUnmapMemory(void *logicalAddress, ACPI_SIZE size) {
}
void *AcpiOsAllocate(ACPI_SIZE size) {
return malloc(size);
}
void AcpiOsFree(void *mem) {
free(mem);
}
uint8_t AcpiOsReadable(void *mem, ACPI_SIZE len) {
return 1;
}
uint8_t AcpiOsWritable(void *mem, ACPI_SIZE len) {
return 1;
}
ACPI_THREAD_ID AcpiOsGetThreadId() {
return task_get_current_tid();
}
ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE type, ACPI_OSD_EXEC_CALLBACK func, void *context) {
task_spawn(func, context);
return AE_OK;
}
void AcpiOsSleep(uint64_t milliseconds) {
k_panics("not supported sleep");
// todo
}
void AcpiOsStall(uint32_t microseconds) {
k_panics("not supported stall");
// todo
}
ACPI_STATUS AcpiOsCreateMutex(ACPI_MUTEX*handle) {
*handle = mutex_create();
return AE_OK;
}
void AcpiOsDeleteMutex(ACPI_MUTEX handle) {
mutex_free(handle);
}
ACPI_STATUS AcpiOsAcquireMutex(ACPI_MUTEX mutex, uint16_t timeout) {
if (timeout != ACPI_WAIT_FOREVER) {
k_panics("sem timeout not supported");
}
mutex_acquire(mutex);
return AE_OK;
}
void AcpiOsReleaseMutex(ACPI_MUTEX mutex) {
mutex_release(mutex);
}
ACPI_STATUS AcpiOsCreateSemaphore(uint32_t maxUnits, uint32_t initialUnits, ACPI_SEMAPHORE*semaphore) {
*semaphore = semaphore_create(initialUnits);
// k_panics("semaphores don't work");
return AE_OK;
}
ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE semaphore) {
semaphore_free(semaphore);
return AE_OK;
}
ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE semaphore, uint32_t units, uint16_t timeout) {
if (timeout != ACPI_WAIT_FOREVER) {
k_panics("sem timeout not supported");
}
for (int i = 0; i < units; ++i) {
semaphore_wait(semaphore);
}
return AE_OK;
}
ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE semaphore, uint32_t units) {
for (int i = 0; i < units; ++i) {
semaphore_signal(semaphore);
}
return AE_OK;
}
ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK*spinlock) {
*spinlock = spinlock_create();
return AE_OK;
}
void AcpiOsDeleteLock(ACPI_SPINLOCK spinlock) {
spinlock_free(spinlock);
}
ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK lock) {
spinlock_acquire(lock);
return 0;
}
void AcpiOsReleaseLock(ACPI_SPINLOCK lock, ACPI_CPU_FLAGS flags) {
spinlock_release(lock);
}
ACPI_STATUS AcpiOsInstallInterruptHandler(uint32_t interruptLevel, ACPI_OSD_HANDLER handler, void *context) {
k_panics("Interrupt not supported yet");
return AE_ERROR;
}
ACPI_STATUS AcpiOsRemoveInterruptHandler(uint32_t interruptNumber, ACPI_OSD_HANDLER handler) {
k_panics("Interrupt not supported yet (r)");
return AE_ERROR;
}
void AcpiOsPrintf(const char *format, ...) {
va_list args;
va_start(args, format);
printf(format, args);
va_end(args);
}
void AcpiOsVprintf(const char *format, va_list args) {
vprintf(format, args);
}
uint64_t AcpiOsGetTimer() {
k_panics("get timer not supported");
return 0;
}
ACPI_STATUS AcpiOsSignal(UINT32 Function, void *Info) {
return AE_OK;
}
void AcpiOsWaitEventsComplete(void) {}
ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExistingTable, ACPI_PHYSICAL_ADDRESS *NewAddress,
UINT32 *NewTableLength) {
*NewAddress = NULL;
*NewTableLength = 0;
return (AE_SUPPORT);
}
ACPI_STATUS AcpiOsReadPciConfiguration(
ACPI_PCI_ID *PciId,
UINT32 Register,
UINT64 *Value,
UINT32 Width) {
k_panics("pci read not supported");
*Value = 0;
return (AE_OK);
}
ACPI_STATUS AcpiOsWritePciConfiguration(
ACPI_PCI_ID *PciId,
UINT32 Register,
UINT64 Value,
UINT32 Width) {
k_panics("pci write not supported");
return (AE_OK);
}
ACPI_STATUS AcpiOsEnterSleep(
UINT8 SleepState,
UINT32 RegaValue,
UINT32 RegbValue) {
return (AE_OK);
}
ACPI_STATUS AcpiOsReadMemory(
ACPI_PHYSICAL_ADDRESS Address,
UINT64 *Value,
UINT32 Width) {
switch (Width) {
case 8:
*Value = ((uint8_t *) Address)[0];
break;
case 16:
*Value = ((uint16_t *) Address)[0];
break;
case 32:
*Value = ((uint32_t *) Address)[0];
break;
case 64:
*Value = ((uint64_t *) Address)[0];
break;
default:
return (AE_BAD_PARAMETER);
break;
}
return (AE_OK);
}
ACPI_STATUS AcpiOsWriteMemory(
ACPI_PHYSICAL_ADDRESS Address,
UINT64 Value,
UINT32 Width) {
switch (Width) {
case 8:
*((uint8_t *) Address) = Value;
break;
case 16:
*((uint16_t *) Address) = Value;
break;
case 32:
*((uint32_t *) Address) = Value;
break;
case 64:
*((uint64_t *) Address) = Value;
break;
default:
return (AE_BAD_PARAMETER);
break;
}
return (AE_OK);
}
ACPI_STATUS AcpiOsReadPort(
ACPI_IO_ADDRESS Address,
UINT32 *Value,
UINT32 Width) {
k_panics("unsupported read");
return AE_ERROR;
}
ACPI_STATUS AcpiOsWritePort(
ACPI_IO_ADDRESS Address,
UINT32 Value,
UINT32 Width) {
k_panics("unsupported write");
return AE_ERROR;
}
void att_noreturn acpi_init(void *data) {
ACPI_STATUS status;
status = AcpiInitializeSubsystem();
if (ACPI_FAILURE(status)) {
k_panics("Failed to init acpi");
}
status = AcpiInitializeTables(NULL, 16, true);
if (ACPI_FAILURE(status)) {
k_panics("Failed to init tables");
}
status = AcpiLoadTables();
if (ACPI_FAILURE(status)) {
k_panics("Failed to load tables");
}
status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
if (ACPI_FAILURE(status)) {
k_panics("Failed to enable acpi");
}
printf("ACPI Initialized");
while (true) {
task_suspend();
}
}
void acpi_init_task() {
task_spawn(acpi_init, NULL);
}
void att_noreturn acpi_shutdown() {
ACPI_STATUS status;
status = AcpiEnterSleepStatePrep(5);
if (ACPI_FAILURE(status)) {
k_panics("failed to prep shutdown");
}
status = AcpiEnterSleepState(5);
if (ACPI_FAILURE(status)) {
k_panics("failed to shutdown");
}
k_panics("Failed");
}
void att_noreturn acpi_restart() {
ACPI_STATUS status;
if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER)) {
k_panics("Could not restart, not available");
}
status = AcpiWrite(AcpiGbl_FADT.ResetValue, &AcpiGbl_FADT.ResetRegister);
if (ACPI_FAILURE(status)) {
k_panics("Failed with status");
}
k_panics("Failed");
}

80
kernel/acpi/lailayer.c Normal file
View File

@@ -0,0 +1,80 @@
//
// Created by rick on 26-08-21.
//
#include <stdio.h>
#include <stdlib.h>
#include <lai/host.h>
#include <myke/acpi/acpi.h>
#include <myke/drivers/ports.h>
#include <myke/libk/libk.h>
const char *lai_loglevel_str(int level) {
switch (level) {
case LAI_DEBUG_LOG:
return "debug ";
case LAI_WARN_LOG:
return "warn ";
default:
return "unknown";
}
}
void laihost_log(int level, const char *msg) {
printf("lai [%s]: %s\n", lai_loglevel_str(level), msg);
}
void laihost_panic(const char *msg) {
k_panics(msg);
}
void *laihost_malloc(size_t size) {
return malloc(size);
}
void *laihost_realloc(void *data, size_t size, size_t old_size) {
return realloc(data, size);
}
void laihost_free(void *data, size_t size) {
free(data);
}
void *laihost_map(size_t address, size_t size) {
return (void *) address;
}
void laihost_unmap(void *pointer, size_t count) {
}
void *laihost_scan(const char *sig, size_t index) {
return acpi_find_table_by_name(sig, (int)index);
}
void laihost_outb(uint16_t port, uint8_t val) {
port_byte_out(port, val);
}
void laihost_outw(uint16_t port, uint16_t val) {
port_word_out(port, val);
}
void laihost_outd(uint16_t port, uint32_t val) {
port_double_word_out(port, val);
}
uint8_t laihost_inb(uint16_t port) {
return port_byte_in(port);
}
uint16_t laihost_inw(uint16_t port) {
return port_word_in(port);
}
uint32_t laihost_ind(uint16_t port) {
return port_double_word_in(port);
}
void laihost_sleep(uint64_t ms) {
return; // todo implement for real system
}

View File

@@ -9,19 +9,24 @@
#include <readline/readline.h>
#include <myke/command.h>
#include <myke/cpu/timer.h>
#include <myke/cpu/pit.h>
#include <myke/drivers/pci/ide.h>
#include <myke/drivers/pci/pci.h>
#include <myke/fs/blockdev.h>
#include <myke/fs/mbr.h>
#include <myke/vfs/blockdev.h>
#include <myke/vfs/part/mbr.h>
#include <myke/libk/libk.h>
#include <myke/mem/malloc.h>
#include <myke/mem/mem.h>
#include <myke/tasks/task.h>
#include <myke/util/power.h>
#include <myke/vfs/vfs.h>
#ifdef ENABLE_SELF_TEST
#include <myke/debug/debug.h>
#include <myke/util/slingurl.h>
#include <myke/libk/syscall.h>
#include <myke/util/init.h>
#endif
@@ -48,14 +53,26 @@ void help(const char *args);
void shutdown(const char *args);
void explode(const char *args);
void ps(const char *args);
void mount(const char *args);
void ls(const char *args);
void cat(const char *args);
#ifdef ENABLE_SELF_TEST
void explode(const char *args);
void kill_self(const char *args);
void exec_self_test(const char *args);
void smash(const char *args);
void slingurl(const char *args);
#endif
cmd_handler cmd_handlers[] = {
@@ -64,35 +81,59 @@ cmd_handler cmd_handlers[] = {
{"print", print},
{"ide", ide},
{"shutdown", shutdown},
{"explode", explode},
{"ps", ps},
{"mount", mount},
{"ls", ls},
{"cat", cat},
#ifdef ENABLE_SELF_TEST
{"slingurl", slingurl},
{"kill-self", kill_self},
{"self-test", exec_self_test},
{"smash", smash},
{"explode", explode},
#endif
{NULL, NULL},
};
#ifdef ENABLE_SELF_TEST
void slingurl(const char *args) {
slingurl_decompose(args);
}
void smash(const char *args) {
// smash the stack, should trigger the stack protector
char data[16];
memset(data, 'A', 32);
}
void kill_self(const char *args) {
syscall_kill_self();
}
void exec_self_test(const char *args) {
// unit tests
self_test();
}
void explode(const char *args) {
// trigger a divide by zero exception
uint32_t x = 0;
uint32_t y = 0;
__asm__("div %%ebx" :
"=a" (x), "=b" (y));
}
#endif
void shutdown(const char *args) {
power_shutdown();
}
void ps(const char *args) {
task_print_all();
}
void print_bootinfo() {
printf("Bootloader name: %s\n"
"cmdline: %s\n",
@@ -154,17 +195,74 @@ void ide(const char *arg) {
}
}
void mount(const char *arg) {
vfs_mount("/", "ide0p0", "ext2");
}
void ls(const char *arg) {
vfs_fd_t *fd = vfs_open("/", 0, 0);
if (fd == NULL) {
printf("could not open /\n");
return;
}
void *data = malloc(1024);
if (data == NULL) {
printf("malloc fail\n");
vfs_close(fd);
return;
}
uint32_t num = 0;
while ((num = vfs_getdents(fd, data, 1024)) > 0) {
vfs_dirent_t *ent = data;
while (true) {
printf("%s\n", ent->name);
if (ent->offset_next >= 1024) {
break;
}
ent = &data[ent->offset_next];
}
}
free(data);
vfs_close(fd);
}
void cat(const char *arg) {
vfs_fd_t *fd = vfs_open("/sda1", 0, 0);
vfs_close(fd);
fd = vfs_open("/test.txt", 0, 0);
if (fd == NULL) {
printf("could not open /test.txt\n");
return;
}
char *data = malloc(1024);
if (data == NULL) {
printf("no mem\n");
vfs_close(fd);
return;
}
int read = vfs_read(fd, data, 1024);
if (read < 0) {
printf("Failed to read\n");
} else if (read == 0) {
printf("emtpy file\n");
} else {
printf("first 10 chars %10s\n", data);
}
free(data);
vfs_close(fd);
}
void store_bootloader_info(multiboot_info_t *multiboot_info) {
// get bootloader and cmdline
if (multiboot_info->flags & MULTIBOOT_INFO_CMDLINE) {
int cmdline_length = strlen((const char *) multiboot_info->cmdline);
size_t cmdline_length = strlen((const char *) multiboot_info->cmdline);
if (cmdline_length > CMDLINE_MAX_LENGTH) {
k_panics("cmdline to long!\n");
}
memcpy(cmdline, (char *) multiboot_info->cmdline, cmdline_length);
}
if (multiboot_info->flags & MULTIBOOT_INFO_BOOT_LOADER_NAME) {
int bootloader_length = strlen((const char *) multiboot_info->boot_loader_name);
size_t bootloader_length = strlen((const char *) multiboot_info->boot_loader_name);
if (bootloader_length > BOOTLOADER_NAME_MAX_LENGTH) {
k_panics("bootloader name to long!\n");
}
@@ -193,3 +291,16 @@ void att_noreturn main_loop(void *data) {
free(msg);
}
}
#ifdef K_SHELL
void main_loop_start() {
task_spawn(main_loop, NULL, "main");
}
INIT_FUNCTION(100) = {
.name = "main-task",
.stage = INIT_STAGE_PRE_TASKING,
.init = main_loop_start,
};
#endif

View File

@@ -16,18 +16,16 @@ union cpu_name {
};
};
static bool has_apic() {
uint32_t eax, unused, edx;
__get_cpuid(CPUID_FEATURE_FLAGS, &eax, &unused, &unused, &edx);
return edx & CPUID_FEAT_EDX_APIC;
}
void cpuidx_print_info() {
union cpu_name name;
__get_cpuid(0, NULL, &name.parts[0], &name.parts[2], &name.parts[1]);
__get_cpuid(CPUID_VENDOR_ID, NULL, &name.parts[0], &name.parts[2], &name.parts[1]);
name.end = 0;
printf("CPU: %s\n", &name.name);
cpu_features_ecx features_ecx;
cpu_features_edx features_edx;
__get_cpuid(1, NULL, NULL, (uint32_t *) &features_ecx, (uint32_t *) &features_edx);
printf("");
}

View File

@@ -7,13 +7,11 @@
#include <myke/cpu/isr.h>
#include <myke/debug/debug.h>
#include <myke/cpu/idt.h>
#include <myke/cpu/pic.h>
#include <myke/cpu/syscall_handler.h>
#include <myke/drivers/ports.h>
#include <myke/libk/libk.h>
#include <myke/tasks/task.h>
#define PIC_END_OF_INTERRUPT 0x20
isr_t interrupt_handlers[256];
void isr_install() {
@@ -51,20 +49,10 @@ void isr_install() {
set_idt_gate(31, (uint32_t) isr31);
// Remap the PIC
// todo make readable
port_byte_out(0x20, 0x11);
port_byte_out(0xA0, 0x11);
port_byte_out(0x21, 0x20);
port_byte_out(0xA1, 0x28);
port_byte_out(0x21, 0x04);
port_byte_out(0xA1, 0x02);
port_byte_out(0x21, 0x01);
port_byte_out(0xA1, 0x01);
port_byte_out(0x21, 0x0);
port_byte_out(0xA1, 0x0);
pic_init(IRQ0);
// Install the IRQs
set_idt_gate(32, (uint32_t) irq0);
set_idt_gate(32, (uint32_t) irq0); // 0x20
set_idt_gate(33, (uint32_t) irq1);
set_idt_gate(34, (uint32_t) irq2);
set_idt_gate(35, (uint32_t) irq3);
@@ -72,7 +60,7 @@ void isr_install() {
set_idt_gate(37, (uint32_t) irq5);
set_idt_gate(38, (uint32_t) irq6);
set_idt_gate(39, (uint32_t) irq7);
set_idt_gate(40, (uint32_t) irq8);
set_idt_gate(40, (uint32_t) irq8); // 0x28
set_idt_gate(41, (uint32_t) irq9);
set_idt_gate(42, (uint32_t) irq10);
set_idt_gate(43, (uint32_t) irq11);
@@ -81,6 +69,7 @@ void isr_install() {
set_idt_gate(46, (uint32_t) irq14);
set_idt_gate(47, (uint32_t) irq15);
// 0x80 SYSCALL
set_idt_gate(128, (uint32_t) isr128);
set_idt(); // Load with ASM
@@ -124,7 +113,7 @@ char *exception_messages[] = {
"Reserved"
};
void isr_handler(isr_registers_t r) {
void att_used isr_handler(isr_registers_t r) {
char msg[256];
if (r.int_no == 128) {
syscall_handle(&r);
@@ -139,11 +128,10 @@ void register_interrupt_handler(uint8_t n, isr_t handler) {
interrupt_handlers[n] = handler;
}
void irq_handler(isr_registers_t r) {
void att_used irq_handler(isr_registers_t r) {
/* After every interrupt we need to send an EOI to the PICs
* or they will not send another interrupt again */
if (r.int_no >= 40) port_byte_out(PORT_PIC_SLAVE_COMMAND, PIC_END_OF_INTERRUPT); /* slave */
port_byte_out(PORT_PIC_MASTER_COMMAND, PIC_END_OF_INTERRUPT); /* master */
pic_eoi(r.int_no >= IRQ8);
if (r.int_no >= IRQ0 && r.int_no < IRQ15) {
task_notify_irq(r.int_no - IRQ0);

30
kernel/cpu/lapic.c Normal file
View File

@@ -0,0 +1,30 @@
//
// Created by rick on 23-08-21.
//
#include <myke/cpu/lapic.h>
void *lapic = NULL;
void lapic_set_addr(uint32_t addr) {
lapic = (void *) addr;
}
void lapic_write(uint32_t offset, uint32_t value) {
*(volatile uint32_t *) ((uintptr_t) lapic + offset) = value;
}
uint32_t lapic_read(uint32_t offset) {
if (lapic == NULL) {
return UINT32_MAX;
}
return *(volatile uint32_t *) ((uintptr_t) lapic + offset);
}
uint32_t lapic_get_id() {
return lapic_read(LAPIC_REG_ID);
}
uint32_t lapic_get_version() {
return lapic_read(LAPIC_REG_VERSION);
}

51
kernel/cpu/pic.c Normal file
View File

@@ -0,0 +1,51 @@
//
// Created by rick on 22-08-21.
//
#include <stdbool.h>
#include <myke/cpu/pic.h>
#include <myke/drivers/ports.h>
// https://wiki.osdev.org/8259_PIC
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
#define PIC_END_OF_INTERRUPT 0x20
void pic_init(uint8_t isr_offset) {
// init both master and slave pic's
port_byte_out(PORT_PIC_MASTER_COMMAND, ICW1_INIT | ICW1_ICW4);
port_byte_out(PORT_PIC_SLAVE_COMMAND, ICW1_INIT | ICW1_ICW4);
// master with ICW4 offset isr_offset, Slave on IRQ2, 8086 mode,
// ICW2
port_byte_out(PORT_PIC_MASTER_DATA, isr_offset); // offset master
port_byte_out(PORT_PIC_SLAVE_DATA, isr_offset + 8); // offset slave
// ICW3
port_byte_out(PORT_PIC_MASTER_DATA, 0x04); // slave PIC at IRQ2
port_byte_out(PORT_PIC_SLAVE_DATA, 0x02); // cascade identity
// ICW4
port_byte_out(PORT_PIC_MASTER_DATA, ICW4_8086); // 8086 mode
port_byte_out(PORT_PIC_SLAVE_DATA, ICW4_8086);
// empty mask
pic_set_mask(0);
}
void pic_set_mask(uint16_t mask) {
port_byte_out(PORT_PIC_MASTER_DATA, mask & 0xFF);
port_byte_out(PORT_PIC_SLAVE_DATA, mask >> 8);
}
void pic_eoi(bool slave) {
if (slave) port_byte_out(PORT_PIC_SLAVE_COMMAND, PIC_END_OF_INTERRUPT); /* slave */
port_byte_out(PORT_PIC_MASTER_COMMAND, PIC_END_OF_INTERRUPT); /* master */
}

View File

@@ -5,7 +5,7 @@
#include <string.h>
#include <stdlib.h>
#include <myke/cpu/timer.h>
#include <myke/cpu/pit.h>
#include <myke/drivers/ports.h>
#include <myke/cpu/isr.h>
#include <myke/libk/libk.h>
@@ -33,19 +33,37 @@
#define PIT_CHANNEL_1 (0b01 << 6)
#define PIT_CHANNEL_2 (0b10 << 6)
#define PIT_CHANNEL_READ_BACK (0b11 << 6)
#define PIT_RB_LATCH_COUNT (0)
#define PIT_RB_LATCH_NO_COUNT (1 << 5)
#define PIT_RB_LATCH_STATUS (0)
#define PIT_RB_LATCH_NO_STATUS (1 << 4)
#define PIT_RB_CHANNEL_2 (1 << 3)
#define PIT_RB_CHANNEL_1 (1 << 2)
#define PIT_RB_CHANNEL_0 (1 << 1)
#define PIT_STATUS_OUTPUT_STATE (1 << 7)
#define PIT_STATUS_NULL_COUNT (1 << 6)
#define PIT_STATUS_ACCESS_MODE (0b11 >> 4)
#define PIT_STATUS_OPERATING_MODE (0b111 < 1)
#define PIT_STATUS_BCD_BIN (1)
#define PIT_FREQUENCY 1193182 /*Hz*/
uint32_t tick = 0;
static void timer_callback(isr_registers_t *regs) {
uint32_t pit_ms_to_div(uint32_t ms) {
uint32_t divisor = PIT_FREQUENCY / ms;
return divisor;
}
static void pit_callback(isr_registers_t *regs) {
tick++;
task_switch_next();
}
uint32_t timer_get_tick() {
uint32_t pit_get_tick() {
return tick;
}
void sleep(uint32_t milliseconds) {
void pit_sleep(uint32_t milliseconds) {
uint32_t done = tick + milliseconds;
while (tick != done) {
k_wait_for_interrupt();
@@ -60,10 +78,10 @@ void print_current_tick() {
kprint("\n");
}
int init_timer(uint32_t freq) {
register_interrupt_handler(IRQ0, timer_callback);
int pit_int_frequency(uint32_t freq) {
register_interrupt_handler(IRQ0, pit_callback);
uint32_t divisor = 1193180 / freq;
uint32_t divisor = PIT_FREQUENCY / freq;
uint8_t low = (uint8_t) (divisor & 0xFF);
uint8_t high = (uint8_t) ((divisor >> 8) & 0xFF);
port_byte_out(PORT_PIT_COMMAND,
@@ -72,3 +90,21 @@ int init_timer(uint32_t freq) {
port_byte_out(PORT_PIT_DATA_0, high);
return 0;
}
// pit_sleep without interrupts
void pit_sleep_ms(const uint32_t sleep) {
// todo locking
uint32_t divider = pit_ms_to_div(sleep);
if (divider > UINT16_MAX) {
k_panics("Sleep for to long");
}
port_byte_out(PORT_PIT_COMMAND,
PIT_MODE_BIN | PIT_MODE_INTERRUPT_ON_TERMINAL_COUNT | PIT_ACCESS_MODE_LH | PIT_CHANNEL_0);
port_byte_out(PORT_PIT_DATA_0, divider & 0xFF);
port_byte_out(PORT_PIT_DATA_0, divider >> 8);
do {
__builtin_ia32_pause();
port_byte_out(PORT_PIT_COMMAND,
PIT_CHANNEL_READ_BACK | PIT_RB_CHANNEL_0 | PIT_RB_LATCH_NO_COUNT | PIT_RB_LATCH_STATUS);
} while (port_byte_in(PORT_PIT_DATA_0) & PIT_STATUS_OUTPUT_STATE);
}

View File

@@ -23,6 +23,11 @@ void syscall_handle(isr_registers_t *registers) {
task_ensure_enabled();
task_suspend();
break;
case SYSCALL_KILL_SELF:
task_ensure_enabled();
task_end(task_get_current_tid());
task_switch_next();
break;
default:
break;
}

View File

@@ -24,7 +24,7 @@ static const char *elf_name_strtab = ".strtab";
struct stackframe {
struct stackframe *ebp;
uint32_t eip;
uintptr_t eip;
};
char *debug_get_shstrtab_entry(uint32_t ndx) {
@@ -80,7 +80,7 @@ void debug_store_info(struct multiboot_info *info) {
debug_find_sections(info->u.elf_sec.shndx);
}
struct elf32_symtab_entry *debug_get_entry_for_addr(uint32_t addr) {
struct elf32_symtab_entry *debug_get_entry_for_addr(uintptr_t addr) {
if (elf_symtab == NULL) {
return NULL;
}
@@ -106,9 +106,9 @@ void debug_backtrace(bool do_sync) {
while (frame->ebp != NULL) {
struct elf32_symtab_entry *entry = debug_get_entry_for_addr(frame->eip);
if (entry == NULL) {
sprintf(msg, "#unknown (%x)\n", frame->eip);
sprintf(msg, "#unknown (%lx)\n", frame->eip);
} else {
sprintf(msg, "%s (%x)\n", debug_get_strtab_entry(entry->st_name), frame->eip);
sprintf(msg, "%s (%lx)\n", debug_get_strtab_entry(entry->st_name), frame->eip);
};
printer(msg);
frame = frame->ebp;

View File

@@ -101,7 +101,7 @@ void test_string() {
const char *strcpy_src_test = "abc\0def";
char *strcpy_dst_test = "\0\0\0\0\0\0\0";
const char *strcpy_expected_test = "abc\0\0\0\0";
assert_int(0, strcpy(strcpy_dst_test, strcpy_src_test));
assert_ptr(strcpy_dst_test, strcpy(strcpy_dst_test, strcpy_src_test));
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpointer-sign"
assert_array_equal(strcpy_dst_test, strcpy_expected_test, 8);

View File

@@ -8,6 +8,7 @@
#include <myke/libc/ringqueue.h>
#include <myke/libk/libk.h>
#include <myke/libk/syscall.h>
#include <myke/util/init.h>
const char scancode_map_lowercase[] = {
@@ -131,7 +132,7 @@ static void keyboard_callback(isr_registers_t *regs) {
publish_key_event(scancode);
}
void init_keyboard() {
void keyboard_init() {
register_interrupt_handler(IRQ1, keyboard_callback);
keyboard_state.shift = 0;
keyboard_state.ctrl = 0;
@@ -139,3 +140,9 @@ void init_keyboard() {
keyboard_state.extended = 0;
keyboard_event_buffer = create_buffer(256, sizeof(KeyEvent));
}
INIT_FUNCTION(100) = {
.name = "keyboard",
.stage = INIT_STAGE_LATE_BOOT,
.init = keyboard_init,
};

View File

@@ -9,12 +9,12 @@
#include <stdlib.h>
#include <sys/types.h>
#include <myke/cpu/timer.h>
#include <myke/cpu/pit.h>
#include <myke/debug/debug.h>
#include <myke/drivers/pci/ide.h>
#include <myke/drivers/pci/pci.h>
#include <myke/drivers/ports.h>
#include <myke/fs/blockdev.h>
#include <myke/vfs/blockdev.h>
#include <myke/libk/kprint.h>
#include <myke/libk/libk.h>
#include <myke/tasks/locking.h>
@@ -395,6 +395,10 @@ void ide_register_block_devices() {
if (!ide_devices[i].reserved) {
continue;
}
if (ide_devices[i].type == IDE_ATAPI) {
// skip ATAPI for now
continue;
}
ide_block_device_info *info = malloc(sizeof(ide_block_device_info)); // todo free for this one
info->device_number = i;
@@ -451,11 +455,11 @@ uint8_t att_used ide_pci_initialize(pci_device *device) {
// (I) Select Drive:
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
sleep(1); // Wait 1ms for drive select to work.
pit_sleep(1); // Wait 1ms for drive select to work.
// (II) Send ATA Identify Command:
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
sleep(1); // This function should be implemented in your OS. which waits for 1 ms.
pit_sleep(1); // This function should be implemented in your OS. which waits for 1 ms.
// it is based on System Timer Device Driver.
// (III) Polling:
@@ -485,7 +489,7 @@ uint8_t att_used ide_pci_initialize(pci_device *device) {
}
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
sleep(1);
pit_sleep(1);
}
// (V) Read Identification Space of the Device:

View File

@@ -2,9 +2,10 @@
// Created by rick on 28-01-21.
//
#include <myke/drivers/serial.h>
#include <sys/types.h>
#include <myke/drivers/ports.h>
#include <myke/libk/kprint.h>
#include <myke/util/init.h>
#define SERIAL_INTERRUPT_DATA_AVAILABLE (1 << 0)
#define SERIAL_INTERRUPT_TRANSMITTER_EMPTY (1 << 1)
@@ -51,7 +52,7 @@
#define MODEM_CONTROL_LOOPBACK_MODE (1 << 4)
#define MODEM_CONTROL_AUTOFLOW_CONTROL_ENABLED (1 << 5)
int serial_init() {
int serial_init_hw() {
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_INTERRUPT, 0); // Disable all interrupts
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_LINE_CONTROL,
LINE_CONTROL_DIVISOR); // Enable DLAB (set baud rate divisor)
@@ -114,4 +115,17 @@ void serial_kprint(const char *msg) {
write_serial(c);
i++;
}
}
}
void serial_init() {
if (serial_init_hw() != 0) {
return;
}
kprint_register(serial_kprint);
}
INIT_FUNCTION(100) = {
.name = "serial",
.stage = INIT_STAGE_EARLY_BOOT_0,
.init = serial_init,
};

View File

@@ -3,9 +3,11 @@
//
#include <string.h>
#include <myke/drivers/vgascreen.h>
#include <myke/drivers/ports.h>
#include <myke/drivers/vgascreen.h>
#include <myke/libk/kprint.h>
#include <myke/util/init.h>
char *_vga_character_memory = (char *) VGA_CHARACTER_MEMORY_LOCATION;
@@ -136,3 +138,14 @@ int get_offset_row(int offset) {
int get_offset_col(int offset) {
return (offset - (get_offset_row(offset) * 2 * VGA_COL_MAX)) / 2;
}
void vga_init() {
vga_clear_screen();
kprint_register(vga_kprint);
}
INIT_FUNCTION(100) = {
.name = "vga",
.stage = INIT_STAGE_EARLY_BOOT_0,
.init = vga_init,
};

View File

@@ -4,37 +4,23 @@
#define DEBUG_INIT
#include <myke/acpi.h>
#include <myke/command.h>
#include <myke/cpu/cpuidx.h>
#include <myke/cpu/gdt.h>
#include <myke/cpu/isr.h>
#include <myke/cpu/timer.h>
#include <myke/cpu/pit.h>
#include <myke/debug/debug.h>
#include <myke/drivers/keyboard.h>
#include <myke/drivers/pci/pci.h>
#include <myke/drivers/serial.h>
#include <myke/drivers/vgascreen.h>
#include <myke/fs/blockdev.h>
#include <myke/libk/kprint.h>
#include <myke/libk/libk.h>
#include <myke/libk/syscall.h>
#include <myke/mem/mem.h>
#include <myke/mem/vmm.h>
#include <myke/util/init.h>
#include <myke/tasks/task.h>
const int version_major = 0,
version_minor = 0,
version_patch = 1;
void init_mmap(multiboot_info_t *multiboot_info) {
if (multiboot_info->flags & (1 << 6)) {
mmap_init_multiboot((struct multiboot_mmap_entry *) multiboot_info->mmap_addr,
multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry));
} else {
k_panics("mmap invalid!\n");
}
}
void init_pci_system() {
pci_scan();
pci_init_drivers();
@@ -43,11 +29,11 @@ void init_pci_system() {
void att_noreturn att_used kmain(multiboot_info_t *multiboot_info, uint32_t mb_name) {
// early init
isr_install();
vga_clear_screen();
vga_clear_screen(' ', VGA_WHITE | (VGA_GRAY << VGA_SHIFT_BG));
kprint_register(vga_kprint);
serial_init();
kprint_register(serial_kprint);
// initialize memory management
vmm_init(multiboot_info);
// initialize early modules (kprint etc.)
init_execute_all(INIT_STAGE_EARLY_BOOT_0);
// parse multiboot
if (mb_name != MULTIBOOT_BOOTLOADER_MAGIC) {
@@ -56,37 +42,33 @@ void att_noreturn att_used kmain(multiboot_info_t *multiboot_info, uint32_t mb_n
store_bootloader_info(multiboot_info);
// initialize memory management
init_mmap(multiboot_info);
// safe multiboot info for later use
debug_store_info(multiboot_info);
gdt_init();
// initialize kprint functionality
kprint_init();
debug_store_info(multiboot_info);
// identify cpu
cpuidx_print_info();
// initialize early driver code (ACPI, etc.)
init_execute_all(INIT_STAGE_EARLY_BOOT_1);
// enable interrupts
__asm__ __volatile__("sti");
// start the timer
init_timer(1000);
// initialize devices
init_keyboard();
pit_int_frequency(1000);
// initialize drivers that are not discovered in any other way
init_execute_all(INIT_STAGE_LATE_BOOT);
// init PCI
init_pci_system();
printf("Booted successfully v%d.%d.%d\n", version_major, version_minor, version_patch);
// initialize tasking
task_init();
kprint_start_task();
block_dev_start_task();
#ifdef K_SHELL
task_spawn(main_loop, NULL);
#endif
acpi_init_task();
// let other system provide tasks (command, kprint, blockdev)
init_execute_all(INIT_STAGE_PRE_TASKING);
// switch to tasking
syscall_start_scheduler();
}

View File

@@ -68,6 +68,11 @@ uint32_t vasprintf(char *buf, const char *fmt, va_list args) {
++i;
}
}
int l = 0;
while (fmt[i] == 'l') {
l++;
i++;
}
switch (fmt[i]) {
case 's': { // string
uint32_t j = 0;
@@ -85,8 +90,14 @@ uint32_t vasprintf(char *buf, const char *fmt, va_list args) {
buf[ptr++] = (char) va_arg(args, int);
break;
case 'x':
case 'p':
case 'X': // todo capitalize
print_int((uint32_t) va_arg(args, uint32_t), field_width, buf, &ptr, 16);
if (l == 0 || l == 1) {
print_int((uint32_t) va_arg(args, uint32_t), field_width, buf, &ptr, 16);
} else if (l == 2) {
print_int((uint64_t) va_arg(args, uint64_t), field_width, buf, &ptr, 16);
}
// todo error
break;
case 'i':
case 'd':

View File

@@ -43,24 +43,21 @@ char *reverse(char *buffer, int i, int j) {
}
// Iterative function to implement itoa() function in C
char *itoa(int value, char *buffer, int base) {
char *itoa(uint32_t value, char *buffer, int base) {
// invalid input
if (base < 2 || base > 32)
return buffer;
// consider absolute value of number
int n = abs(value);
int i = 0;
while (n) {
int r = n % base;
while (value) {
uint32_t r = value % base;
if (r >= 10)
buffer[i++] = 65 + (r - 10);
else
buffer[i++] = 48 + r;
n = n / base;
value = value / base;
}
// if number is 0

View File

@@ -5,27 +5,37 @@
#include <string.h>
#include <sys/param.h>
#include <sys/types.h>
#include <myke/mem/malloc.h>
int memcpy(void *dst, const void *src, size_t amount) {
void *memcpy(void *dst, const void *src, size_t amount) {
for (size_t i = 0; i < amount; i++) {
((char *) dst)[i] = ((const char *) src)[i];
}
return 0;
return dst;
}
int memset(void *dst, int data, size_t amount) {
void *memset(void *dst, int data, size_t amount) {
for (size_t i = 0; i < amount; ++i) {
((char *) dst)[i] = (char) data;
}
return 0;
return dst;
}
void *memmove(void *dst, const void *src, size_t amount) {
void *tmp = malloc(amount);
if (tmp == NULL) {
return NULL;
}
memcpy(dst, memcpy(tmp, src, amount), amount);
free(tmp);
return dst;
}
int strcpy(char *dst, const char *src) {
void *strcpy(char *dst, const char *src) {
return memcpy(dst, src, strlen(src) + 1);
}
int strncpy(char *dst, const char *src, size_t n) {
void *strncpy(char *dst, const char *src, size_t n) {
return memcpy(dst, src, MIN(strlen(src), n) + 1);
}
@@ -38,16 +48,19 @@ size_t strlen(const char *str) {
}
int strcmp(const char *s1, const char *s2) {
int len1 = strlen(s1);
int len2 = strlen(s2);
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
return strncmp(s1, s2, MAX(len1, len2));
}
const char *strchr(const char *s, char c) {
int index = 0;
char *strchr(const char *s, char c) {
size_t index = 0;
while (1) {
if (s[index] == c) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
return &s[index];
#pragma clang diagnostic pop
}
if (s[index] == 0) {
return NULL;
@@ -56,19 +69,35 @@ const char *strchr(const char *s, char c) {
}
}
char *strrchr(const char *s, char c) {
size_t index = strlen(s);
while (1) {
if (s[index] == c) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
return &s[index];
#pragma clang diagnostic pop
}
if (index == 0) {
return NULL;
}
index--;
}
}
int memcmp(const void *s1, const void *s2, size_t n) {
uint8_t a, b;
for (size_t i = 0; i < n; ++i) {
a = ((uint8_t *) s1)[i];
b = ((uint8_t *) s2)[i];
if (a > b) return 1;
if (b < a) return -1;
if (a < b) return -1;
}
return 0;
}
int strncmp(const char *s1, const char *s2, int n) {
for (int i = 0; i < n; ++i) {
int strncmp(const char *s1, const char *s2, size_t n) {
for (size_t i = 0; i < n; ++i) {
if (s1[i] == 0 && s2[i] == 0) {
return 0;
}
@@ -105,3 +134,14 @@ char *strncat(char *dest, const char *src, size_t n) {
}
return dest;
}
char *strdup(const char *s) {
return strndup(s, strlen(s));
}
char *strndup(const char *s, size_t n) {
char *new = malloc(n + 1);
memcpy(new, s, n);
new[n] = 0;
return new;
}

View File

@@ -9,12 +9,13 @@
#include <myke/libk/kprint.h>
#include <myke/tasks/task.h>
#include <myke/util/stream.h>
#include <myke/util/init.h>
#define MAX_HANDLERS 8
#define STREAM_SIZE (32*1024)
#define PRINT_BUFFER_SIZE 64
stream_t *kprint_stream;
stream_t *kprint_stream = NULL;
kprint_handler handlers[MAX_HANDLERS] = {0};
@@ -29,7 +30,11 @@ void kprint_register(kprint_handler handler) {
}
void kprint(const char *msg) {
stream_write(kprint_stream, (const uint8_t *) msg, strlen(msg));
if (kprint_stream == NULL) {
kprint_sync(msg);
} else {
stream_write(kprint_stream, (const uint8_t *) msg, strlen(msg));
}
}
void kprint_internal(const char *msg) {
@@ -64,5 +69,11 @@ void att_noreturn kprint_task(void *_) {
}
void kprint_start_task() {
task_spawn(kprint_task, NULL);
}
task_spawn(kprint_task, NULL, "kprint");
}
INIT_FUNCTION(100) = {
.name = "kprint-task",
.stage = INIT_STAGE_PRE_TASKING,
.init = kprint_start_task,
};

View File

@@ -21,6 +21,10 @@ void att_noreturn k_panics(const char *msg) {
k_panic();
}
void att_noreturn k_not_implemented() {
k_panics("Not Implemented");
}
void att_noreturn k_panic() {
kprint_sync("PANIC!");
while (1) {

View File

@@ -35,3 +35,7 @@ void syscall_yield_irq(uint16_t irq) {
void syscall_job_suspend() {
syscall1(SYSCALL_SUSPEND);
}
void syscall_kill_self() {
syscall1(SYSCALL_KILL_SELF);
}

View File

@@ -282,7 +282,7 @@ static struct liballoc_major *allocate_new_page(unsigned int size) {
}
void *malloc(size_t req_size) {
void __attribute__((assume_aligned (16), alloc_size (1), malloc)) *malloc(size_t req_size) {
int startedBet = 0;
unsigned long long bestSize = 0;
void *p = NULL;
@@ -725,7 +725,7 @@ void free(void *ptr) {
void *calloc(size_t nobj, size_t size) {
int real_size;
size_t real_size;
void *p;
real_size = nobj * size;

View File

@@ -2,7 +2,6 @@
// Created by rick on 22-04-20.
//
#include <attributes.h>
#include <stdio.h>
#include <sys/types.h>
@@ -22,10 +21,10 @@
#define MMAP_TYPE_PAGING 7
typedef struct {
uint32_t address;
uintptr_t address;
uint32_t length;
uint32_t type;
} att_packed mmap_entry;
} mmap_entry;
int last_memmap_entry = 0;
mmap_entry memmap[MEMMAP_ENTRIES] = {
@@ -49,7 +48,7 @@ mmap_entry memmap[MEMMAP_ENTRIES] = {
void use_mmap_entry(struct multiboot_mmap_entry *entry) {
mmap_entry *mm_entry = &memmap[last_memmap_entry++];
mm_entry->address = (void *) entry->addr;
mm_entry->address = (uintptr_t) entry->addr;
mm_entry->length = entry->len;
mm_entry->type = entry->type;
// check if the entry overlaps with the kernel address space

View File

@@ -2,58 +2,80 @@
// Created by rick on 21-02-21.
//
#include <attributes.h>
#include <stdbool.h>
#include <sys/types.h>
#include <attributes.h>
#include <myke/mem/paging.h>
#include <sys/param.h>
#define TABLE_ADDR_MASK 0xFFFFF000
#define DIRECTORY_SIZE 1024
#define PAGING_DIR_INDEX(virt) ((virt) >> 22)
#define PAGING_TABLE_INDEX(virt) ((virt) >> 12 & 0x03FF)
const uint32_t x = TABLE_ADDR_MASK;
typedef struct {
union {
struct {
bool present: 1;
bool read_write: 1;
bool user_mode: 1;
bool write_through: 1;
bool cache_disabled: 1;
bool accessed: 1;
char ignored: 1;
bool page_size: 1;
bool global: 1; // ignored
uint8_t avail: 3;
} att_packed;
uint32_t addr;
};
} att_packed page_directory_entry;
#define KERNEL_OFFSET 0xC0000000
typedef struct {
union {
struct {
bool present: 1;
bool read_write: 1;
bool user_supervisor: 1;
bool write_through: 1;
bool cache_disabled: 1;
bool accessed: 1;
bool dirty: 1;
char ignored: 1;
bool global: 1;
uint8_t available: 3;
} att_packed;
uint32_t addr;
};
} att_packed page_table_entry;
// One page table, only 4M
#define PAGING_STATE_EARLY 0
#define PAGING_STATE_FULL 60
page_directory_entry page_directory[DIRECTORY_SIZE] att_aligned(4096);
page_directory_entry att_aligned(4096) kernel_page_directory[DIRECTORY_SIZE] = {0};
void page_pre_init() {
for (int i = 0; i < DIRECTORY_SIZE; ++i) {
page_directory[i].read_write = true;
page_directory[i].user_mode = false;
page_directory[i].present = false;
int paging_state = PAGING_STATE_EARLY;
void paging_load_directory(uintptr_t physical_address) {
asm volatile("mov %%eax, %%cr3" : : "a" (physical_address));
}
uintptr_t paging_get_current_directory_physical() {
uintptr_t directory_address;
asm volatile("mov %%cr3, %%eax" : "=a" (directory_address));
return directory_address;
}
page_directory_entry *paging_get_current() {
return kernel_page_directory;
}
int paging_map_4m(uintptr_t physical_address, uintptr_t virtual_address, int count, int mode) {
if (virtual_address & ~PAGING_MASK_4M || physical_address & PAGING_MASK_4M) {
// address not 4M aligned
return PAGING_RESULT_ALIGN;
}
page_directory_entry *dir = paging_get_current();
for (int i = 0; i < count; ++i) {
page_directory_entry current_val = dir[PAGING_DIR_INDEX(virtual_address) + i];
if (current_val & DIRECTORY_PRESENT_MASK) {
return PAGING_RESULT_INUSE;
}
}
page_directory_entry mask = DIRECTORY_PAGE_SIZE_MASK;
if (mode & PAGING_MODE_RW) {
mask |= DIRECTORY_RW_MASK;
}
if (mode & PAGING_MODE_US) {
mask |= DIRECTORY_US_MASK;
}
for (int i = 0; i < count; ++i) {
dir[PAGING_DIR_INDEX(virtual_address) + i] = physical_address & mask;
}
paging_load_directory((uintptr_t) dir);
return PAGING_RESULT_OK;
}
int paging_map_memory(uintptr_t physical_address, uintptr_t virtual_address, int count, int mode) {
if (mode & PAGING_MODE_4M) {
return paging_map_4m(physical_address, virtual_address, count, mode);
}
if (paging_state < PAGING_STATE_FULL) {
// can't allocate 4K pages yet
if ((virtual_address & ~PAGING_MASK_4M) != (physical_address & ~PAGING_MASK_4M)) {
return PAGING_RESULT_ERR; // not in same pos in 4M page
}
int table_index = PAGING_TABLE_INDEX(virtual_address);
int pages = DIV_ROUND_UP(table_index + count, 1024);
return paging_map_4m(physical_address & PAGING_MASK_4M,
virtual_address & PAGING_MASK_4M,
pages,
mode | PAGING_MODE_4M);
}
return PAGING_RESULT_ERR;
}

24
kernel/mem/vmm.c Normal file
View File

@@ -0,0 +1,24 @@
//
// Created by rick on 17-10-21.
//
#include <sys/types.h>
#include <myke/libk/libk.h>
#include <myke/mem/mem.h>
#include <myke/mem/vmm.h>
void vmm_init(multiboot_info_t *multiboot_info) {
if (!(multiboot_info->flags & MULTIBOOT_INFO_MEM_MAP)) {
k_panics("No MMAP info available");
}
mmap_init_multiboot((struct multiboot_mmap_entry *) multiboot_info->mmap_addr,
multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry));
}
void* vmm_map_physical(uintptr_t physical) {
}
void* vmm_unmap_physical(uintptr_t physical) {
}
void* vmm_unmap_virtual(uintptr_t virtual) {
}

View File

@@ -12,7 +12,7 @@
#include <myke/libk/syscall.h>
typedef struct lock_fifo_entry {
uint32_t tid;
pid_t tid;
struct lock_fifo_entry *next;
} lock_fifo_entry_t;

View File

@@ -4,12 +4,14 @@
#include <attributes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <myke/cpu/cpu.h>
#include <myke/libk/libk.h>
#include <myke/mem/pmm.h>
#include <myke/libk/syscall.h>
#include <myke/tasks/task.h>
#define stack_end(task) ((task)->stack + ((task)->stack_page_count * PAGE_SIZE))
@@ -23,22 +25,45 @@
#define TASK_STATE_STOPPED (1 << 6)
#define TASK_STATE_ERROR (1 << 7)
const char *task_state_str(uint8_t state) {
switch (state) {
case TASK_STATE_RUNNABLE:
return "RUNNABLE ";
case TASK_STATE_RUNNING:
return "RUNNING ";
case TASK_STATE_WAIT_IRQ:
return "WAIT_IRQ ";
case TASK_STATE_WAIT_SIGNAL:
return "WAIT_SIGNAL";
case TASK_STATE_STOPPED:
return "STOPPED ";
case TASK_STATE_ERROR:
return "ERROR ";
case TASK_STATE_UNKNOWN:
default:
return "UNKNOWN ";
}
}
int errno = 0;
typedef struct task {
// state
bool present: 1;
uint8_t state;
uint16_t wait_irq;
uint32_t tid;
int errno;
// identity
pid_t tid;
char *name;
// linked list
struct task *next;
// persistence/memory
int errno;
void *stack;
uint32_t stack_page_count;
task_registers_t *task_registers;
} task_t;
@@ -57,19 +82,23 @@ task_t *first_task = NULL;
task_t *last_task = NULL;
task_t *current_task = NULL;
uint32_t last_tid = 0;
pid_t last_tid = 0;
extern switch_task(task_registers_t
**, task_registers_t*);
pid_t reaper_pid = 0;
extern void switch_task(task_registers_t **, task_registers_t *);
extern att_cdecl att_noreturn void __task_entry_point();
extern att_noreturn void __task_entry_point_inner();
// internal api
void task_free(task_t *task);
// explicit cdecl calling convention
void att_cdecl att_noreturn task_entry_point(task_entrypoint entrypoint, void *entry_data) {
void att_unused att_cdecl att_noreturn task_entry_point(task_entrypoint entrypoint, void *entry_data) {
entrypoint(entry_data);
// task_end_self();
syscall_kill_self();
while (true); // halt
}
@@ -91,11 +120,11 @@ void task_lock_free() {
}
}
uint32_t task_get_current_tid() {
pid_t task_get_current_tid() {
return current_task->tid;
}
void task_signal(uint32_t tid) {
void task_signal(pid_t tid) {
task_t *t = first_task;
while (t != NULL) {
if (t->tid == tid) {
@@ -114,10 +143,47 @@ void task_suspend() {
task_switch_next();
}
// internal tasks
void att_noreturn task_idle(void *data) {
while (true) __asm__("hlt");
}
void att_noreturn task_reaper(void *data) {
while (true) {
bool did_reap = false;
task_lock_acquire();
task_t *t = first_task;
task_t *p = first_task;
task_t *n = NULL;
while (t != NULL) {
n = t->next;
if (t->state == TASK_STATE_STOPPED) {
did_reap = true;
if (t == first_task) {
if (n == NULL) {
k_panics("No more tasks");
}
first_task = n;
task_free(t);
t = NULL;
} else {
p->next = n;
task_free(t);
t = p;
}
}
p = t;
t = n;
}
task_lock_free();
if (did_reap) {
syscall_yield_job();
} else {
syscall_job_suspend();
}
}
}
void task_notify_irq(uint8_t irq_no) {
uint16_t irq__bit = 1 << irq_no;
task_t *t = first_task;
@@ -198,10 +264,11 @@ void task_switch_next() {
task_switch_next_inner(task_first_runnable());
}
task_t *task_create(task_entrypoint entrypoint, void *entry_data) {
task_t *task_create(task_entrypoint entrypoint, void *entry_data, char *name) {
task_t *new_task = malloc(sizeof(task_t));
memset((uint8_t *) new_task, 0, sizeof(task_t));
new_task->tid = last_tid++;
new_task->name = strdup(name);
new_task->state = TASK_STATE_RUNNABLE;
new_task->stack = pmm_get_pages(16);
@@ -233,12 +300,19 @@ task_t *task_create(task_entrypoint entrypoint, void *entry_data) {
}
void task_init() {
idle_task = task_create(task_idle, NULL);
void task_free(task_t *task) {
pmm_free_pages(task->stack, 16);
free(task->name);
free(task);
}
uint32_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
task_t *new_task = task_create(entrypoint, entry_data);
void task_init() {
idle_task = task_create(task_idle, NULL, "idle");
reaper_pid = task_spawn(task_reaper, NULL, "reaper");
}
pid_t task_spawn(task_entrypoint entrypoint, void *entry_data, char *name) {
task_t *new_task = task_create(entrypoint, entry_data, name);
if (first_task == NULL) {
// first task
first_task = new_task;
@@ -249,13 +323,27 @@ uint32_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
return new_task->tid;
}
void task_end(uint32_t tid) {
void task_end(pid_t tid) {
task_t *t = first_task;
while (t != NULL) {
if (t->tid == tid) {
t->state = TASK_STATE_STOPPED;
task_signal(reaper_pid);
break;
}
t = t->next;
}
}
void task_print_all() {
// acquiring task lock as reference to current task may disappear
// might overrun kprint buffer
task_lock_acquire();
printf("tasks:\n");
task_t *c = first_task;
while (c != NULL) {
printf("%d - %s %s\n", c->tid, task_state_str(c->state), c->name);
c = c->next;
}
task_lock_free();
}

21
kernel/util/init.c Normal file
View File

@@ -0,0 +1,21 @@
//
// Created by rick on 13-08-21.
//
#include <myke/util/init.h>
#include <stdio.h>
extern struct init __start_init[];
extern struct init __stop_init[];
#define NUM_DRIVERS ((size_t)(__stop_init - __start_init))
#define DRIVER(i) ((__start_init) + (i))
void init_execute_all(enum init_stage stage) {
for (size_t i = 0; i < NUM_DRIVERS; ++i) {
if (DRIVER(i)->stage != stage) continue;
if (stage > INIT_STAGE_EARLY_BOOT_0) {
printf("init %s\n", DRIVER(i)->name);
}
DRIVER(i)->init();
}
}

View File

@@ -4,13 +4,12 @@
#include <attributes.h>
#include <myke/drivers/ports.h>
#include <lai/helpers/pm.h>
#include <myke/libk/libk.h>
#include <myke/util/power.h>
void att_noreturn power_shutdown() {
port_word_out(PORT_ACPI, PORT_ACPI_SHUTDOWN);
port_word_out(PORT_QEMU_COMMAND, PORT_QEMU_COMMAND_SHUTDOWN);
port_word_out(PORT_VBOX, PORT_VBOX_SHUTDOWN);
lai_enter_sleep(5);
k_panics("Failed to shut down!\n");
}

71
kernel/util/slingurl.c Normal file
View File

@@ -0,0 +1,71 @@
//
// Created by rick on 26-03-21.
//
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <myke/mem/malloc.h>
void slingurl_decompose(const char* url) {
uint32_t urllen = strlen(url);
if (urllen <= 0) {
printf("Url empty");
return;
}
char* lurl = malloc(urllen + 1);
strcpy(lurl, url);
// get path section
char* path = lurl;
// find fist selector
char* selector = strchr(lurl, '.');
int nselectors = 0;
// to lazy to deal with urls without selectors and extension
if (selector == NULL) goto free_malloc;
selector[0] = 0;
selector += 1;
// find suffix
char* suffix = strchr(selector, '/');
if (suffix != NULL) {
suffix[0] = 0;
suffix += 1;
}
// pick last "suffix" as extension
char* extension = strrchr(selector, '.');
if (extension == NULL) {
// no dots in suffix section, so only an extension
extension = selector;
selector = NULL;
} else {
extension[0] = 0;
extension += 1;
}
if (selector != NULL) {
nselectors = 1;
char* cselector = selector;
while ((cselector = strchr(cselector, '.')) != NULL) {
cselector[0] = 0;
cselector += 1;
nselectors++;
}
}
printf("path: %s\n", path);
printf("selectors: ");
char* cselector = selector;
for (int i = 0; i < nselectors; ++i) {
printf("%s,", cselector);
cselector += strlen(cselector) + 1;
}
printf("\n");
printf("extension: %s\n", extension);
printf("suffix: %s\n", suffix);
free_malloc:
free(lurl);
}

View File

@@ -4,13 +4,13 @@
#include <attributes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <myke/fs/blockdev.h>
#include <myke/vfs/blockdev.h>
#include <myke/libk/libk.h>
#include <myke/tasks/locking.h>
#include <myke/tasks/task.h>
#include <myke/util/init.h>
#define MAX_BLOCK_DEVS 64
@@ -25,6 +25,25 @@ extern struct block_dev_driver __stop_block_dev_driver[];
semaphore_t *block_semaphore;
bool blockdev_task_running = false;
block_device_t *block_dev_get_by_id(const char *name) {
for (int i = 0; i < last_block_dev; ++i) {
if (block_devices[i].flags.present
&& strcmp(block_devices[i].identifier, name) == 0) {
return &block_devices[i];
}
}
return NULL;
}
block_dev_driver_t *block_dev_driver_by_name(const char *name) {
for (size_t i = 0; i < NUM_DRIVERS; ++i) {
if (strcmp(DRIVER(i)->name, name) == 0) {
return DRIVER(i);
}
}
return NULL;
}
uint8_t block_dev_register(block_device_t *device) {
if (last_block_dev >= MAX_BLOCK_DEVS - 1) {
return BLOCK_DEV_REGISTER_FULL;
@@ -38,6 +57,25 @@ uint8_t block_dev_register(block_device_t *device) {
return BLOCK_DEV_REGISTER_OK;
}
void *block_dev_mount(const char *device, const char *driver_name) {
if (device == NULL || driver_name == NULL || strlen(device) == 0 || strlen(driver_name) == 0) {
return NULL; // invalid input
}
block_device_t *dev = block_dev_get_by_id(device);
if (dev == NULL) {
return NULL;
}
block_dev_driver_t *driver = block_dev_driver_by_name(driver_name);
if (driver == NULL) {
return NULL;
}
if (driver->check_device(dev) == BLOCK_DEV_DRIVER_CHECK_OK) {
dev->driver = driver;
return dev->driver_info;
}
return NULL;
}
void block_dev_free(block_device_t *device) {
//todo
k_panics("block dev free not supported");
@@ -51,53 +89,10 @@ int block_dev_num_not_scanned() {
return not_scanned;
}
bool block_dev_mount(char *identifier, char *driver_name) {
bool result = true;
block_device_t *device = NULL;
for (int i = 0; i < last_block_dev; ++i) {
if (strncmp(block_devices[i].identifier, identifier, 16) == 0) {
device = &block_devices[i];
}
}
if (identifier == NULL) {
result = false;
goto _end;
}
struct block_dev_driver *driver = NULL;
for (size_t j = 0; j < NUM_DRIVERS; ++j) {
if (strncmp(DRIVER(j)->name, driver_name, 16) == 0) {
driver = DRIVER(j);
}
}
if (driver == NULL) {
result = false;
goto _end;
}
uint8_t *lba0 = malloc(device->block_size);
uint8_t read_result = device->access(device, BLOCK_DEV_DIRECTION_READ, 0, 1, lba0);
if (read_result != BLOCK_DEV_ACCESS_OK) {
result = false;
goto _access_fail;
}
if (driver->check_device(device, lba0) != BLOCK_DEV_DRIVER_CHECK_OK) {
result = false;
}
_access_fail:
free(lba0);
_end:
return result;
}
void block_dev_scan() {
int c_last_block_dev = last_block_dev;
for (int i = 0; i < c_last_block_dev; ++i) {
if (block_devices[i].flags.scanned || !block_devices[i].flags.present) continue;
uint8_t *lba0 = malloc(block_devices[i].block_size);
uint8_t read_result = block_devices[i].access(&block_devices[i], BLOCK_DEV_DIRECTION_READ, 0, 1, lba0);
if (read_result != BLOCK_DEV_ACCESS_OK) {
block_devices[i].flags.unreadable = 1;
goto _block_dev_scan_free;
}
for (size_t j = 0; j < NUM_DRIVERS; ++j) {
// only partitioning drivers are automatically assigned
if (!DRIVER(i)->flags.partitioning) {
@@ -109,15 +104,13 @@ void block_dev_scan() {
}
// let the driver test the disk
uint8_t driver_result = DRIVER(j)->check_device(&block_devices[i], lba0);
uint8_t driver_result = DRIVER(j)->check_device(&block_devices[i]);
if (driver_result == BLOCK_DEV_DRIVER_CHECK_OK) {
block_devices[i].driver = DRIVER(j);
block_devices[i].flags.driver_installed = 1;
break;
}
}
_block_dev_scan_free:
free(lba0);
block_devices[i].flags.scanned = 1;
}
}
@@ -132,7 +125,7 @@ void att_noreturn block_dev_task(void *data) {
void block_dev_start_task() {
block_semaphore = semaphore_create(1);
blockdev_task_running = true;
task_spawn(block_dev_task, NULL);
task_spawn(block_dev_task, NULL, "blockdev");
}
void block_dev_print_info() {
@@ -142,4 +135,10 @@ void block_dev_print_info() {
block_devices[i].identifier,
block_devices[i].flags.driver_installed ? block_devices[i].driver->name : "n/a");
}
}
}
INIT_FUNCTION(100) = {
.name = "blockdev-task",
.stage = INIT_STAGE_PRE_TASKING,
.init = block_dev_start_task,
};

437
kernel/vfs/lfs/ext2.c Normal file
View File

@@ -0,0 +1,437 @@
//
// Created by rick on 19-09-21.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <myke/vfs/blockdev.h>
#include <myke/vfs/lfs/ext2.h>
#include <myke/vfs/vfs-driver.h>
#include <myke/libk/libk.h>
#include <sys/param.h>
// https://wiki.osdev.org/Ext2
#define EXT2_DRIVER_NAME "ext2"
#define MI(mount) ((ext2_mount_info_t *)(mount)->global_driver_data)
#define FDI(fd) ((ext2_fd_info_t *)(fd)->driver_data)
typedef struct ext2_dgetents_state {
uint32_t bp;
void *current_data;
void *current_data_pos;
void *current_data_end;
uint32_t cur;
bool at_end_of_block;
} ext2_dgetents_state_t;
typedef struct ext2_fd_info {
uint32_t inode_nr;
ext2_inode_t *inode;
size_t seek_position;
ext2_dgetents_state_t *dgetents_state;
size_t size;
bool dgetents_done;
} ext2_fd_info_t;
#define EXT2_READ_OK 0
#define EXT2_READ_ENOMEM 1
#define EXT2_READ_IOERR 2
#define EXT2_READ_EOF 3
int ext2_read_blocks(vfs_mount_t *mount, uint32_t block, uint32_t num, void *target) {
uint32_t lba = (block * MI(mount)->block_size) / BLOCK_DEV_LBA_SIZE;
uint32_t num_lba = DIV_ROUND_UP(num * MI(mount)->block_size, BLOCK_DEV_LBA_SIZE);
void *buffer = malloc(num_lba * BLOCK_DEV_LBA_SIZE);
if (buffer == NULL) {
return EXT2_READ_ENOMEM;
}
if (((block_device_t *) MI(mount)->block_dev)->access(
(block_device_t *) MI(mount)->block_dev,
BLOCK_DEV_DIRECTION_READ, lba, num_lba, buffer)
!= BLOCK_DEV_ACCESS_OK) {
free(buffer);
return EXT2_READ_IOERR; // todo
}
memcpy(target, buffer, MI(mount)->block_size);
free(buffer);
return EXT2_READ_OK;
}
ext2_bg_descriptor_t *ext2_get_bg_descriptor(vfs_mount_t *mount, uint32_t idx) {
uint32_t bg_per_block = MI(mount)->block_size / sizeof(ext2_bg_descriptor_t);
uint32_t block = idx / bg_per_block;
if (MI(mount)->block_size != 1024) {
k_panics("only 1024 supported for now");
}
block += 2;
ext2_bg_descriptor_t *blocks = malloc(MI(mount)->block_size);
if (blocks == NULL) {
return NULL;
}
if (ext2_read_blocks(mount, block, 1, blocks) != EXT2_READ_OK) {
free(blocks);
return NULL;
}
ext2_bg_descriptor_t *res = malloc(sizeof(ext2_bg_descriptor_t));
if (res == NULL) {
free(blocks);
return NULL;
}
uint32_t block_index = idx % bg_per_block;
memcpy(res, &blocks[block_index], sizeof(ext2_bg_descriptor_t));
free(blocks);
return res;
}
ext2_bg_descriptor_t *ext2_get_bg_descriptor_for_inode(vfs_mount_t *mount, uint32_t inode) {
uint32_t group_idx = (inode - 1) / MI(mount)->sb.no_inodes_per_group;
if (group_idx > MI(mount)->no_block_groups) {
return NULL; // todo report
}
ext2_bg_descriptor_t *result = ext2_get_bg_descriptor(mount, group_idx);
if (result == NULL) {
return NULL;
}
return result;
}
ext2_inode_t *ext2_get_inode(vfs_mount_t *mount, uint32_t inode) {
if (inode > MI(mount)->sb.total_inodes) {
return NULL; // todo report
}
ext2_bg_descriptor_t *descriptor = ext2_get_bg_descriptor_for_inode(mount, inode);
if (descriptor == NULL) {
return NULL;
}
uint8_t *inodes_in_group = malloc(MI(mount)->block_size);
if (inodes_in_group == NULL) {
free(descriptor);
return NULL;
}
uint32_t inode_index = (inode - 1) % MI(mount)->sb.no_inodes_per_group;
uint32_t block = (inode_index * MI(mount)->sb.size_inode) / MI(mount)->block_size;
uint32_t inode_offset = (inode_index * MI(mount)->sb.size_inode) % MI(mount)->block_size;
// todo check bitmap?
if (ext2_read_blocks(mount, descriptor->start_block_inode + block, 1, inodes_in_group) != EXT2_READ_OK) {
free(descriptor);
return NULL;
}
free(descriptor);
ext2_inode_t *node = malloc(sizeof(ext2_inode_t));
memcpy(node, &inodes_in_group[inode_offset], sizeof(ext2_inode_t));
free(inodes_in_group);
return node;
}
int ext2_get_block_from_inode(vfs_mount_t *mount, vfs_fd_t *fd, void *target, uint32_t block_idx) {
if (block_idx < 12) {
uint32_t bp = FDI(fd)->inode->dbp[block_idx];
if (bp == 0) {
return EXT2_READ_EOF;
}
return ext2_read_blocks(mount, bp, 1, target);
} else {
k_not_implemented();
}
}
#define EXT2_DGETENT_CONT 1
#define EXT2_DGETENT_FULL 2
#define EXT2_DGETENT_END 3
#define EXT2_DGETENT_ERR 4
int ext2_dgetent_next(vfs_mount_t *mount, vfs_fd_t *fd, ext2_dgetents_state_t *state, void *target, size_t offset,
size_t max_size) {
if (state->bp == UINT32_MAX) {
// new
state->current_data = malloc(MI(mount)->block_size);
state->current_data_pos = state->current_data;
state->current_data_end = state->current_data + MI(mount)->block_size;
state->bp = 0;
state->at_end_of_block = false;
int result = ext2_get_block_from_inode(mount, fd, state->current_data, state->bp);
if (result != EXT2_READ_OK) {
return result == EXT2_READ_EOF ? EXT2_DGETENT_END : EXT2_DGETENT_ERR;
}
}
if (state->at_end_of_block == true) {
state->bp += 1;
int result = ext2_get_block_from_inode(mount, fd, state->current_data, state->bp);
state->current_data_pos = state->current_data;
if (result != EXT2_READ_OK) {
return result == EXT2_READ_EOF ? EXT2_DGETENT_END : EXT2_DGETENT_ERR;
}
}
ext2_dir_entry_t *ent = state->current_data_pos;
if (VFS_DIRENT_SIZE(ent->name_size) > max_size) {
return EXT2_DGETENT_FULL;
}
vfs_mk_dirent_record(&target[offset], ent->inode, offset, 0, &ent->name, ent->name_size);
state->current_data_pos += ent->ent_size;
if (state->current_data_pos >= state->current_data_end) {
state->at_end_of_block = true;
}
return EXT2_DGETENT_CONT;
}
int ext2_vfs_mount(vfs_mount_t *mount) {
ext2_mount_info_t *mount_info = block_dev_mount(mount->device, EXT2_DRIVER_NAME);
if (mount_info == NULL) {
return VFS_MOUNT_ERROR;
}
mount->global_driver_data = mount_info;
return VFS_MOUNT_OK;
}
ext2_fd_info_t *ext2_get_inode_info(vfs_mount_t *mount, uint32_t inode) {
ext2_inode_t *node = ext2_get_inode(mount, inode);
if (node == NULL) {
return NULL;
}
ext2_fd_info_t *driver_data = malloc(sizeof(ext2_fd_info_t));
if (driver_data == NULL) {
return NULL;
}
size_t size = node->size_l;
if (MI(mount)->sb.features_optional & EXT2_FEATURE_RO_64BIT_SIZE && node->type == EXT2_INODE_TYPE_FILE) {
#if EXT2_FEAT_RO_64BIT_SIZE
size += node->size_h << 32;
#else
if (node->size_h != 0) {
printf("WARN: file to large");
free(driver_data);
return NULL;
}
#endif
}
driver_data->inode_nr = inode;
driver_data->inode = node;
driver_data->size = size;
driver_data->seek_position = 0;
driver_data->dgetents_state = NULL;
driver_data->dgetents_done = false;
return driver_data;
}
vfs_dirent_t *ext2_get_dirent_for_filename(vfs_mount_t *mount, vfs_fd_t *dir, const char *path) {
size_t name_length = strlen(path);
vfs_dirent_t *ent = malloc(VFS_DIRENT_MAX_SIZE);
if (ent == NULL) {
return NULL;
}
ext2_dgetents_state_t *state = malloc(sizeof(ext2_dgetents_state_t));
if (state == NULL) {
return NULL;
}
memset(state, 0, sizeof(ext2_dgetents_state_t));
state->bp = UINT32_MAX;
bool found = false;
// todo hash algorithm
while (true) {
const int result = ext2_dgetent_next(mount, dir, state, ent, 0, VFS_DIRENT_MAX_SIZE);
if (result == EXT2_DGETENT_FULL || result == EXT2_DGETENT_ERR) {
break; // whut
}
if (result == EXT2_DGETENT_END) {
// not found
break; // not found
}
if (name_length != strlen(ent->name)) {
continue;
}
if (strncmp(path, ent->name, name_length) != 0) {
// not same name
continue;
}
found = true;
break;
}
free(state);
if (!found) {
free(ent);
return NULL;
}
return ent;
}
int ext2_vfs_open(vfs_mount_t *mount, vfs_fd_t *dir, const char *path, int mode, vfs_fd_t *out) {
if (dir == NULL && path == NULL) {
ext2_fd_info_t *driver_data = ext2_get_inode_info(mount, EXT2_ROOT_INODE);
if (driver_data == NULL) {
return VFS_OPEN_ERROR;
}
out->driver_data = driver_data;
return VFS_OPEN_OK;
}
vfs_dirent_t *dirent = ext2_get_dirent_for_filename(mount, dir, path);
int open_result = VFS_OPEN_ERROR;
if (dirent != NULL) {
ext2_fd_info_t *driver_data = ext2_get_inode_info(mount, dirent->inode);
if (driver_data != NULL) {
out->driver_data = driver_data;
open_result = VFS_OPEN_OK;
}
}
free(dirent);
return open_result;
}
int ext2_vfs_close(vfs_mount_t *mount, vfs_fd_t *fd) {
if (FDI(fd)->dgetents_state != NULL) {
free(FDI(fd)->dgetents_state);
}
free(fd);
return VFS_CLOSE_OK;
}
int ext2_vfs_fstat(vfs_mount_t *mount, vfs_fd_t *fd, stat_t *target, int flags) {
target->st_dev = 0; // todo
target->st_ino = FDI(fd)->inode_nr;
target->st_mode = FDI(fd)->inode->type;
target->st_nlink = FDI(fd)->inode->no_hard_links;
target->st_uid = FDI(fd)->inode->uid;
target->st_gid = FDI(fd)->inode->gid;
target->st_size = FDI(fd)->size;
target->st_blksize = MI(mount)->block_size;
target->st_blocks = FDI(fd)->size / 512; // todo correct?
target->st_atim.tv_sec = FDI(fd)->inode->last_access;
target->st_mtim.tv_sec = FDI(fd)->inode->last_mod;
target->st_ctim.tv_sec = FDI(fd)->inode->created;
if (FDI(fd)->inode->type == EXT2_INODE_TYPE_BLOCK_DEV || FDI(fd)->inode->type == EXT2_INODE_TYPE_CHAR_DEV) {
target->st_rdev = FDI(fd)->inode->dbp[0];
}
return 0;
}
int ext2_vfs_fread(vfs_mount_t *mount, vfs_fd_t *fd, void *target, size_t size) {
size_t target_pos = 0;
void *buffer = malloc(MI(mount)->block_size);
if (buffer == NULL) {
return VFS_READ_ERROR;
}
while (true) {
uint32_t block = FDI(fd)->seek_position / MI(mount)->block_size;
uint32_t bytes_read_in_block = FDI(fd)->seek_position % MI(mount)->block_size;
uint32_t bytes_left_in_block = MI(mount)->block_size - bytes_read_in_block;
size_t toread = MIN(MIN(bytes_left_in_block, size - target_pos), FDI(fd)->size - target_pos);
if (ext2_get_block_from_inode(mount, fd, buffer, block) != EXT2_READ_OK) {
free(buffer);
return VFS_READ_ERROR;
}
memcpy(&target[target_pos], &buffer[block], toread);
target_pos += toread;
FDI(fd)->seek_position += toread;
if (target_pos == size || FDI(fd)->seek_position >= FDI(fd)->size) {
break;
}
}
free(buffer);
return target_pos;
}
int ext2_vfs_dgetent(vfs_mount_t *mount, vfs_fd_t *fd, void *target, size_t size) {
if (FDI(fd)->dgetents_done == true) {
return 0;
}
size_t offset = 0;
size_t prev_offset = 0;
if (FDI(fd)->dgetents_state == NULL) {
FDI(fd)->dgetents_state = malloc(sizeof(ext2_dgetents_state_t));
FDI(fd)->dgetents_state->bp = UINT32_MAX;
FDI(fd)->dgetents_state->cur = 0;
}
while (true) {
int result = ext2_dgetent_next(mount, fd, FDI(fd)->dgetents_state, target, offset, size - offset);
if (result != EXT2_DGETENT_CONT) {
if (result == EXT2_DGETENT_END) {
if (FDI(fd)->dgetents_state->current_data != NULL) {
free(FDI(fd)->dgetents_state->current_data);
FDI(fd)->dgetents_state->current_data = NULL;
}
free(FDI(fd)->dgetents_state);
FDI(fd)->dgetents_state = NULL;
FDI(fd)->dgetents_done = true;
}
if (result == EXT2_DGETENT_FULL || result == EXT2_DGETENT_END) {
((vfs_dirent_t *) &target[prev_offset])->offset_next = size;
}
break;
}
size_t reclen = ((vfs_dirent_t *) &target[offset])->reclen;
prev_offset = offset;
offset += reclen;
}
return offset;
}
uint32_t ext2_get_no_bg(ext2_sb_t *sb) {
uint32_t no_bg_by_blocks = DIV_ROUND_UP(sb->total_blocks, sb->no_blocks_per_group);
uint32_t no_bg_by_inodes = DIV_ROUND_UP(sb->total_inodes, sb->no_inodes_per_group);
if (no_bg_by_blocks != no_bg_by_inodes) {
k_panics("No no match");
}
return no_bg_by_inodes;
}
uint8_t ext2_check_device(block_device_t *device) {
ext2_sb_t *sb = malloc(EXT2_SB_SIZE);
if (device->access(device,
BLOCK_DEV_DIRECTION_READ,
EXT2_SB_ADDR / BLOCK_DEV_LBA_SIZE,
EXT2_SB_SIZE / BLOCK_DEV_LBA_SIZE,
sb) != BLOCK_DEV_ACCESS_OK) {
free(sb);
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
}
if (sb->ext2_signature != EXT2_SIGNATURE) {
printf("Missing signature\n");
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
}
printf("Ext2 features:\n\tRequired: %lx\n\tOptional: %lx\n\tRo: %lx\n", sb->features_required,
sb->features_optional, sb->features_ro);
if (sb->features_required ^ EXT2_FEAT_REQ_SUPPORTED) {
printf("Filesystem uses features not supported by implementation, %lx\n", sb->features_required);
free(sb);
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
}
printf("ext2 valid\n");
ext2_mount_info_t *mount_info = malloc(sizeof(ext2_mount_info_t));
memcpy(&mount_info->sb, sb, sizeof(ext2_sb_t));
mount_info->no_block_groups = ext2_get_no_bg(sb);
mount_info->block_size = 1024 << sb->block_size;
mount_info->fragment_size = 1024 << sb->fragment_size;
mount_info->block_dev = device;
device->driver_info = mount_info;
free(sb);
return BLOCK_DEV_DRIVER_CHECK_OK;
}
BLOCK_DEV_DRIVER(300) = {
.name = EXT2_DRIVER_NAME,
.check_device = ext2_check_device,
.free_device = NULL,
};
VFS_DRIVER(300) = {
.name = EXT2_DRIVER_NAME,
.vfs_mount = ext2_vfs_mount,
.open = ext2_vfs_open,
.close = ext2_vfs_close,
.fstat = ext2_vfs_fstat,
.fread = ext2_vfs_fread,
.dgetent = ext2_vfs_dgetent,
};

View File

@@ -8,7 +8,7 @@
#include <string.h>
#include <sys/types.h>
#include <myke/fs/blockdev.h>
#include <myke/vfs/blockdev.h>
#define FAT_TYPE_12 1
#define FAT_TYPE_16 2
@@ -107,9 +107,26 @@ void print_chars(char *chars, int amount) {
}
}
uint8_t att_used fat_check_device(const block_device_t *device, uint8_t *first_sector) {
uint8_t att_used fat_check_device(const block_device_t *device) {
uint8_t *first_sector = malloc(512);
if (first_sector == NULL) {
printf("No mem\n");
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
}
uint8_t result = device->access(device, BLOCK_DEV_DIRECTION_READ, 0, 1, first_sector);
if (result != BLOCK_DEV_ACCESS_OK) {
printf("Could not access device\n");
free(first_sector);
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
}
if (first_sector[510] != 0x55 || first_sector[511] != 0xAA) {
printf("No boot signature\n");
free(first_sector);
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
}
fat_bpb bpb;
memcpy((uint8_t *) &bpb, first_sector, sizeof(fat_bpb));
free(first_sector);
if (bpb.bpb.sectors_per_fat == 0 || bpb.bpb.sectors_per_cluster == 0) {
printf("Definitely not FAT\n");
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;

View File

@@ -7,7 +7,7 @@
#include <string.h>
#include <sys/types.h>
#include <myke/fs/blockdev.h>
#include <myke/vfs/blockdev.h>
typedef struct {
char filename[100];
@@ -75,15 +75,20 @@ ustar_sector *ustar_next(ustar_sector *current) {
return ustar_sector_valid(next) ? next : NULL;
}
uint8_t ustar_check_device(const block_device_t *device, uint8_t *first_sector) {
ustar_sector *sector = (ustar_sector *) first_sector;
uint8_t ustar_check_device(const block_device_t *device) {
ustar_sector *sector = malloc(512); // todo fix leak
if (device->access(device, BLOCK_DEV_DIRECTION_READ, 0, 1, sector) != BLOCK_DEV_ACCESS_OK) {
free(sector);
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
}
if (!ustar_sector_valid(sector)) {
free(sector);
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
}
ustar_fs *fs = malloc(sizeof(ustar_fs));
fs->first_inode = malloc(sizeof(ustar_inode));
memcpy(&fs->first_inode->sector, first_sector, sizeof(ustar_sector));
memcpy(&fs->first_inode->sector, sector, sizeof(ustar_sector));
fs->first_inode->lba = 0;
fs->device = device;

View File

@@ -9,8 +9,8 @@
#include <sys/types.h>
#include <myke/drivers/pci/ide.h>
#include <myke/fs/blockdev.h>
#include <myke/fs/mbr.h>
#include <myke/vfs/blockdev.h>
#include <myke/vfs/part/mbr.h>
typedef struct {
uint8_t bootable;
@@ -33,12 +33,11 @@ typedef struct {
} att_packed mbr_table;
typedef struct {
const block_device_t *device;
block_device_t *device;
uint32_t start_lba;
} mbr_block_driver_info;
uint8_t
mbr_block_dev_access(const block_device_t *device, uint8_t direction, uint32_t lba, uint8_t sectors, void *target) {
uint8_t mbr_block_dev_access(block_device_t *device, uint8_t direction, uint32_t lba, uint8_t sectors, void *target) {
if (!device->flags.present || lba > device->num_lba) {
return BLOCK_DEV_ACCESS_ERR;
}
@@ -52,9 +51,15 @@ mbr_block_dev_access(const block_device_t *device, uint8_t direction, uint32_t l
return info->device->access(info->device, direction, actual_lba, sectors, target);
}
uint8_t att_used mbr_check_device(const block_device_t *device, uint8_t *first_sector) {
uint8_t mbr_check_device(block_device_t *device) {
uint8_t *first_sector = malloc(512);
if (device->access(device, BLOCK_DEV_DIRECTION_READ, 0, 1, first_sector) != BLOCK_DEV_ACCESS_OK) {
free(first_sector);
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
}
mbr_table table;
memcpy((uint8_t *) &table, first_sector + (device->block_size - sizeof(mbr_table)), sizeof(mbr_table));
free(first_sector);
if (table.signature[0] != 0x55 && table.signature[1] != 0xAA) { // AA 55 but in little endian
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
}

14
kernel/vfs/tmpfs.c Normal file
View File

@@ -0,0 +1,14 @@
//
// Created by rick on 13-08-21.
//
#include <myke/util/init.h>
void tmpfs_init() {
}
INIT_FUNCTION(100) = {
.name = "tmpfs",
.stage = INIT_STAGE_AFTER_BOOT_PRE_INIT,
.init = tmpfs_init,
};

186
kernel/vfs/vfs.c Normal file
View File

@@ -0,0 +1,186 @@
//
// Created by rick on 12-08-21.
//
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <myke/tasks/locking.h>
#include <myke/vfs/vfs.h>
#include <myke/vfs/vfs-driver.h>
#include <myke/util/init.h>
#include <myke/libk/libk.h>
vfs_mount_t *first_mount = NULL;
mutex_t *mount_lock = NULL;
extern vfs_driver_t __start_vfs_driver[];
extern vfs_driver_t __stop_vfs_driver[];
#define NUM_DRIVERS ((size_t)(__stop_vfs_driver - __start_vfs_driver))
#define DRIVER(i) ((__start_vfs_driver) + (i))
vfs_driver_t *vfs_get_driver_by_name(const char *name) {
for (size_t i = 0; i < NUM_DRIVERS; ++i) {
if (strcmp(DRIVER(i)->name, name) == 0) {
return DRIVER(i);
}
}
return NULL;
}
void vfs_register_mount(vfs_mount_t *mount) {
mutex_acquire(mount_lock);
if (first_mount == NULL) {
first_mount = mount;
} else {
vfs_mount_t *last_mount = first_mount;
while (last_mount->next != NULL) last_mount = last_mount->next;
last_mount->next = mount;
}
mutex_release(mount_lock);
}
vfs_mount_t *vfs_get_mount_for_path(const char *path) {
if (first_mount == NULL) {
return NULL;
}
mutex_acquire(mount_lock);
size_t max_length = strlen(path);
vfs_mount_t *longest_match = NULL;
size_t match_length = 0;
vfs_mount_t *last_mount = NULL;
do {
if (last_mount == NULL) {
last_mount = first_mount;
} else if ((last_mount = last_mount->next) == NULL) {
break;
}
size_t mount_length = strlen(last_mount->prefix);
if (mount_length > max_length || mount_length < match_length) {
continue;
}
if (strncmp(last_mount->prefix, path, strlen(last_mount->prefix)) == 0) {
longest_match = last_mount;
match_length = mount_length;
}
} while (true);
mutex_release(mount_lock);
return longest_match;
}
int vfs_mount(const char *path, const char *device, const char *driver) {
vfs_driver_t *driver_impl = vfs_get_driver_by_name(driver);
if (driver_impl == NULL) {
return VFS_MOUNT_ERROR;
}
vfs_mount_t *mount = malloc(sizeof(vfs_mount_t));
mount->driver = driver_impl;
mount->device = device;
mount->prefix = path;
int result = driver_impl->vfs_mount(mount);
if (result != VFS_MOUNT_OK) {
free(mount);
return result;
}
vfs_register_mount(mount);
return VFS_MOUNT_OK;
}
vfs_fd_t *vfs_open_intermediate(vfs_mount_t *mount, const char *path, int flags, int mode) {
vfs_fd_t *intermediate_dir = malloc(sizeof(vfs_fd_t));
vfs_fd_t *out = malloc(sizeof(vfs_fd_t));
out->mount = mount;
intermediate_dir->mount = mount;
char *full_path = strdup(path);
char *current_path = full_path;
while (strlen(current_path) > 0) {
if (current_path[0] == '/') {
// root
if (((vfs_driver_t *) mount->driver)->open(mount, NULL, NULL, flags, out) != VFS_OPEN_OK) {
free(out);
free(intermediate_dir);
free(full_path);
return NULL;
}
current_path = &current_path[1];
} else {
char *next_dir = strchr(current_path, '/');
if (next_dir != NULL) {
next_dir[0] = 0;
}
if (((vfs_driver_t *) mount->driver)->open(mount, intermediate_dir, current_path, flags, out) !=
VFS_OPEN_OK) {
((vfs_driver_t *) mount->driver)->close(mount, intermediate_dir);
free(out);
free(intermediate_dir);
free(full_path);
return NULL;
}
if (next_dir == NULL) {
current_path = &current_path[strlen(current_path)];
} else {
current_path = &next_dir[1];
}
if (((vfs_driver_t *) mount->driver)->close(mount, intermediate_dir) != VFS_CLOSE_OK) {
free(out);
free(intermediate_dir);
free(full_path);
return NULL;
}
}
memcpy(intermediate_dir, out, sizeof(vfs_fd_t));
}
free(full_path);
free(intermediate_dir);
return out;
}
// https://man7.org/linux/man-pages/man2/open.2.html
vfs_fd_t *vfs_open(const char *path, int flags, int mode) {
vfs_mount_t *mount = vfs_get_mount_for_path(path);
if (mount == NULL) {
return NULL;
}
return vfs_open_intermediate(mount, &path[strlen(mount->prefix) - 1], flags, mode);
}
void vfs_close(vfs_fd_t *fd) {
((vfs_driver_t *) (fd->mount->driver))->close(fd->mount, fd);
free(fd);
}
// https://man7.org/linux/man-pages/man2/stat.2.html
int vfs_fstat(vfs_fd_t *dirfd, stat_t *target, int flags) {
return ((vfs_driver_t *) (dirfd->mount->driver))->fstat(dirfd->mount, dirfd, target, flags);
}
// https://man7.org/linux/man-pages/man2/read.2.html
int vfs_read(vfs_fd_t *fd, void *target, size_t size) {
return ((vfs_driver_t *) (fd->mount->driver))->fread(fd->mount, fd, target, size);
}
// inspiration https://man7.org/linux/man-pages/man2/getdents.2.html
int vfs_getdents(vfs_fd_t *fd, void *target, int count) {
return ((vfs_driver_t *) fd->mount->driver)->dgetent(fd->mount, fd, target, count);
}
void vfs_mk_dirent_record(vfs_dirent_t *ent, uint32_t inode, uint32_t cur_offset, uint8_t type, char *name,
size_t name_length) {
ent->inode = inode;
strncpy(ent->name, name, name_length);
ent->name[name_length] = 0;
ent->type = type;
ent->reclen = VFS_DIRENT_SIZE(name_length);
ent->offset_next = cur_offset + ent->reclen;
}
void vfs_init() {
mount_lock = mutex_create();
}
INIT_FUNCTION(100) = {
.name = "vfs-task",
.stage = INIT_STAGE_PRE_TASKING,
.init = vfs_init,
};

1
lai Submodule

Submodule lai added at 432546ee09

110
linker.ld
View File

@@ -6,54 +6,76 @@ ENTRY(_start)
kernel image. */
SECTIONS
{
/* Begin putting sections at 1 MiB, a conventional place for kernels to be
loaded at by the bootloader. */
. = 1M;
_kernel_start = .;
/* Begin putting sections at 1 MiB, a conventional place for kernels to be
loaded at by the bootloader. */
. = 1M;
_kernel_start = .;
.data.boot ALIGN(4K) : {
*(.multiboot)
*(.data.boot)
}
.text.boot ALIGN(4K) : {
*(.text.boot)
}
.bss.boot ALIGN(4K) : {
*(.bss.boot)
}
/* First put the multiboot header, as it is required to be put very early
early in the image or the bootloader won't recognize the file format.
Next we'll put the .text section. */
.text BLOCK(4K) : ALIGN(4K)
{
*(.multiboot)
*(.text)
}
. += 0xC0000000;
/* First put the multiboot header, as it is required to be put very early
early in the image or the bootloader won't recognize the file format.
Next we'll put the .text section. */
.text ALIGN(4K) : AT(ADDR(.text)-0xC0000000)
{
*(.text)
}
/* Read-only data. */
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.rodata)
}
/* Read-only data. */
.rodata ALIGN(4K) : AT(ADDR(.rodata)-0xC0000000)
{
*(.rodata)
}
/* Read-write data (initialized) */
.data BLOCK(4K) : ALIGN(4K)
{
*(.data)
. = ALIGN(16);
__start_pci_driver = .;
*(SORT(.pci_driver.*))
__stop_pci_driver = .;
. = ALIGN(16);
__start_block_dev_driver = .;
*(SORT(.block_dev_driver.*))
__stop_block_dev_driver = .;
}
/* Read-write data (initialized) */
.data ALIGN(4K) : AT(ADDR(.data)-0xC0000000)
{
*(.data)
/* Read-write data (uninitialized) and stack */
.bss BLOCK(4K) : ALIGN(4K)
{
*(COMMON)
*(.bss)
}
_kernel_end = .;
. = ALIGN(16);
__start_pci_driver = .;
*(SORT(.pci_driver.*))
__stop_pci_driver = .;
/DISCARD/ : {
*(.eh_frame);
*(.comment);
*(.note.gnu.build-id);
}
. = ALIGN(16);
__start_block_dev_driver = .;
*(SORT(.block_dev_driver.*))
__stop_block_dev_driver = .;
/* The compiler may produce other sections, by default it will put them in
a segment with the same name. Simply add stuff here as needed. */
. = ALIGN(16);
__start_vfs_driver = .;
*(SORT(.vfs_driver.*))
__stop_vfs_driver = .;
. = ALIGN(16);
__start_init = .;
*(SORT(.init.*))
__stop_init = .;
}
/* Read-write data (uninitialized) and stack */
.bss ALIGN(4K) : AT(ADDR(.bss)-0xC0000000)
{
*(COMMON)
*(.bss)
}
_kernel_end = . - 0xC0000000;
/DISCARD/ : {
*(.eh_frame);
*(.comment);
*(.note.gnu.build-id);
}
/* The compiler may produce other sections, by default it will put them in
a segment with the same name. Simply add stuff here as needed. */
}

3
rootfs/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
mnt/*
!mnt
rootfs.img

52
rootfs/mkrootfs.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/bin/bash
IMG_FILE=rootfs.img
IMG_SIZE=100 # MB
function log() {
echo "$*"
}
function yes_or_no() {
while true; do
read -p "$* [y/n]: " yn
case $yn in
[Yy]*) return 0 ;;
[Nn]*)
echo "Aborted"
return 1
;;
esac
done
}
function setup_lb() {
sudo losetup -fP --show ${IMG_FILE}
}
if [ ! -d mnt ]; then
mkdir mnt
fi
if [ -f "${IMG_FILE}" ]; then
log "${IMG_FILE} already exists"
if ! yes_or_no "Continue?"; then
exit 1
fi
fi
# build img
dd if=/dev/zero of=${IMG_FILE} bs=1M count=${IMG_SIZE}
parted -s ${IMG_FILE} mktable msdos
parted -s ${IMG_FILE} mkpart primary ext2 0 100%
LB_DEV="$(setup_lb)"
if [ -z "${LB_DEV}" ]; then
log "Failed to setup loobback"
exit 1
fi
sudo mkfs.ext2 -L rootfs "${LB_DEV}p1"
sudo mount "${LB_DEV}p1" mnt

39
rootfs/mount_rootfs.sh Executable file
View File

@@ -0,0 +1,39 @@
#!/bin/bash
IMG_FILE=rootfs.img
IMG_SIZE=100 # MB
function log() {
echo "$*"
}
function yes_or_no() {
while true; do
read -p "$* [y/n]: " yn
case $yn in
[Yy]*) return 0 ;;
[Nn]*)
echo "Aborted"
return 1
;;
esac
done
}
function setup_lb() {
sudo losetup -fP --show ${IMG_FILE}
}
if [ ! -f "${IMG_FILE}" ]; then
log "${IMG_FILE} doesn't exist"
exit 1
fi
LB_DEV="$(setup_lb)"
if [ -z "${LB_DEV}" ]; then
log "Failed to setup loobback"
exit 1
fi
sudo mount "${LB_DEV}p1" mnt

15
rootfs/umount_rootfsh.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
function log() {
echo "$*"
}
LB_DEV=$(findmnt -n -o SOURCE mnt)
if [ -z "${LB_DEV}" ]; then
log "Not mounted"
exit 1
fi
sudo umount mnt
sudo losetup -d "${LB_DEV%p1}"