Compare commits
20 Commits
feature/ap
...
feature/mo
| Author | SHA1 | Date | |
|---|---|---|---|
| b71dc48311 | |||
| 1dc0942b4d | |||
| e850dabc8b | |||
| 6d898c07e8 | |||
| 03f0ec6f88 | |||
| 073051c99e | |||
| e693b12915 | |||
| e37222c346 | |||
| 462dd90890 | |||
| a7bd154c32 | |||
| ad023a8119 | |||
| 6b0f6ddfb7 | |||
| 8187265735 | |||
| f047e692c9 | |||
| c172a5cb8a | |||
| 3034a5d417 | |||
| 94c6332e27 | |||
| be71f9a7e9 | |||
| ee4338fedd | |||
| 8152ad6e9a |
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
|||||||
[submodule "acpica"]
|
[submodule "lai"]
|
||||||
path = acpica
|
path = lai
|
||||||
url = https://github.com/acpica/acpica
|
url = https://github.com/managarm/lai.git
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
project(new_kernel C ASM)
|
project(new_kernel C ASM)
|
||||||
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|
||||||
# Define compiler run time
|
# Define compiler run time
|
||||||
SET(COMPILER_RT ${CMAKE_CURRENT_LIST_DIR}/compiler/target/bin)
|
SET(COMPILER_RT ${CMAKE_CURRENT_LIST_DIR}/compiler/target/bin)
|
||||||
@@ -12,43 +13,55 @@ SET(CMAKE_ASM_COMPILER ${COMPILER_RT}/i686-elf-gcc)
|
|||||||
# Set compile flags
|
# Set compile flags
|
||||||
SET(CMAKE_C_FLAGS "-g -ffreestanding -Wall -Wextra -fno-exceptions -fstack-protector -fno-pie -m32")
|
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_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 directory
|
||||||
include_directories(AFTER acpica/source/include)
|
include_directories(AFTER include)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
################
|
||||||
|
# Features #
|
||||||
|
################
|
||||||
|
|
||||||
|
set(ENABLE_ACPI ON CACHE BOOL "Enable ACPI Suppport")
|
||||||
|
|
||||||
|
####################
|
||||||
|
# ACPI Feature #
|
||||||
|
####################
|
||||||
|
if (ENABLE_ACPI)
|
||||||
|
include_directories(AFTER lai/include)
|
||||||
|
FILE(GLOB lai lai/core/*.c lai/helpers/*.c lai/driver/*.c)
|
||||||
|
ELSE()
|
||||||
|
set(lai)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Other sourcees
|
||||||
FILE(GLOB_RECURSE kernel_src kernel/**.c)
|
FILE(GLOB_RECURSE kernel_src kernel/**.c)
|
||||||
FILE(GLOB_RECURSE kernel_asm kernel/**.S)
|
FILE(GLOB_RECURSE kernel_asm kernel/**.S)
|
||||||
FILE(GLOB_RECURSE boot_asm boot/boot.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(__KERNEL__)
|
|
||||||
add_compile_definitions(__MYKE__)
|
#######################
|
||||||
|
# Kernel Features #
|
||||||
|
#######################
|
||||||
|
|
||||||
|
# ACPI
|
||||||
|
if (ENABLE_ACPI)
|
||||||
|
add_compile_definitions(ENABLE_ACPI)
|
||||||
|
endif ()
|
||||||
|
|
||||||
# Run IDE in DMA mode if available (NYI)
|
# Run IDE in DMA mode if available (NYI)
|
||||||
#add_compile_definitions(IDE_ENABLE_INTERRUPT)
|
#add_compile_definitions(IDE_ENABLE_INTERRUPT)
|
||||||
# Run the kernel shell as the main task
|
# Kernel Command Line features
|
||||||
add_compile_definitions(ENABLE_SELF_TEST) # Support for pretty printing pci class/subclass/interface
|
add_compile_definitions(ENABLE_K_SHELL) # Run the kernel shell as the main task
|
||||||
|
add_compile_definitions(ENABLE_SELF_TEST) # Compile in self test kernel CLI command
|
||||||
add_compile_definitions(ENABLE_PCIPP) # Support for pretty printing pci class/subclass/interface
|
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_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
1
acpica
Submodule acpica deleted from 63db9761a6
@@ -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)
|
|
||||||
394
include/acmyke.h
394
include/acmyke.h
@@ -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__ */
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
// function
|
// function
|
||||||
#define att_noreturn __attribute((noreturn))
|
#define att_noreturn __attribute((noreturn))
|
||||||
#define att_cdecl __attribute((cdecl))
|
#define att_cdecl __attribute((cdecl))
|
||||||
|
#define att_unused __attribute((unused))
|
||||||
// structure
|
// structure
|
||||||
#define att_packed __attribute((packed))
|
#define att_packed __attribute((packed))
|
||||||
// field
|
// field
|
||||||
|
|||||||
@@ -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
10
include/myke/acpi/acpi.h
Normal 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
|
||||||
256
include/myke/acpi/structures.h
Normal file
256
include/myke/acpi/structures.h
Normal 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
|
||||||
@@ -9,6 +9,4 @@
|
|||||||
|
|
||||||
void store_bootloader_info(multiboot_info_t *multiboot_info);
|
void store_bootloader_info(multiboot_info_t *multiboot_info);
|
||||||
|
|
||||||
void main_loop(void *data);
|
|
||||||
|
|
||||||
#endif //NEW_KERNEL_COMMAND_H
|
#endif //NEW_KERNEL_COMMAND_H
|
||||||
|
|||||||
@@ -7,74 +7,13 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct {
|
enum {
|
||||||
bool sse3: 1;
|
CPUID_VENDOR_ID = 0x00,
|
||||||
bool pclmul: 1;
|
CPUID_FEATURE_FLAGS = 0x01,
|
||||||
bool dtes64: 1;
|
CPUID_CACHE
|
||||||
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;
|
|
||||||
|
|
||||||
typedef struct {
|
enum {
|
||||||
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 {
|
|
||||||
CPUID_FEAT_ECX_SSE3 = 1 << 0,
|
CPUID_FEAT_ECX_SSE3 = 1 << 0,
|
||||||
CPUID_FEAT_ECX_PCLMUL = 1 << 1,
|
CPUID_FEAT_ECX_PCLMUL = 1 << 1,
|
||||||
CPUID_FEAT_ECX_DTES64 = 1 << 2,
|
CPUID_FEAT_ECX_DTES64 = 1 << 2,
|
||||||
@@ -134,6 +73,8 @@ enum cpu_features {
|
|||||||
CPUID_FEAT_EDX_PBE = 1 << 31
|
CPUID_FEAT_EDX_PBE = 1 << 31
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool has_apic();
|
||||||
|
|
||||||
void cpuidx_print_info();
|
void cpuidx_print_info();
|
||||||
|
|
||||||
#endif //NEW_KERNEL_CPUIDX_H
|
#endif //NEW_KERNEL_CPUIDX_H
|
||||||
|
|||||||
23
include/myke/cpu/lapic.h
Normal file
23
include/myke/cpu/lapic.h
Normal 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
17
include/myke/cpu/pic.h
Normal 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
|
||||||
@@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
int init_timer(uint32_t freq);
|
int pit_int_frequency(uint32_t freq);
|
||||||
|
|
||||||
void print_current_tick();
|
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
|
#endif //MY_KERNEL_TIMER_H
|
||||||
@@ -19,8 +19,6 @@ typedef struct KeyEvent_t {
|
|||||||
|
|
||||||
char getc();
|
char getc();
|
||||||
|
|
||||||
void init_keyboard();
|
|
||||||
|
|
||||||
//const char *key_code_to_string(KeyCode key);
|
//const char *key_code_to_string(KeyCode key);
|
||||||
|
|
||||||
KeyEvent *get_next_event();
|
KeyEvent *get_next_event();
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -27,8 +27,4 @@
|
|||||||
#define VGA_COL_MAX 80
|
#define VGA_COL_MAX 80
|
||||||
#define VGA_ROW_MAX 25
|
#define VGA_ROW_MAX 25
|
||||||
|
|
||||||
void vga_clear_screen();
|
|
||||||
|
|
||||||
void vga_kprint(const char *msg);
|
|
||||||
|
|
||||||
#endif //MY_KERNEL_VGASCREEN_H
|
#endif //MY_KERNEL_VGASCREEN_H
|
||||||
|
|||||||
@@ -17,6 +17,4 @@ void kprint(const char *msg);
|
|||||||
|
|
||||||
void kprint_sync(const char *msg);
|
void kprint_sync(const char *msg);
|
||||||
|
|
||||||
void kprint_init();
|
void kprint_init();
|
||||||
|
|
||||||
void kprint_start_task();
|
|
||||||
@@ -21,4 +21,6 @@ void att_noreturn k_panics(const char *msg);
|
|||||||
|
|
||||||
void att_noreturn k_panic();
|
void att_noreturn k_panic();
|
||||||
|
|
||||||
|
void att_noreturn k_not_implemented();
|
||||||
|
|
||||||
#endif //NEW_KERNEL_LIBK_H
|
#endif //NEW_KERNEL_LIBK_H
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#define SYSCALL_YIELD_JOB 0x02
|
#define SYSCALL_YIELD_JOB 0x02
|
||||||
#define SYSCALL_YIELD_IRQ 0x03
|
#define SYSCALL_YIELD_IRQ 0x03
|
||||||
#define SYSCALL_SUSPEND 0x04
|
#define SYSCALL_SUSPEND 0x04
|
||||||
|
#define SYSCALL_KILL_SELF 0x05
|
||||||
|
|
||||||
void att_noreturn syscall_start_scheduler();
|
void att_noreturn syscall_start_scheduler();
|
||||||
|
|
||||||
@@ -21,4 +22,6 @@ void syscall_yield_irq(uint16_t irq);
|
|||||||
|
|
||||||
void syscall_job_suspend();
|
void syscall_job_suspend();
|
||||||
|
|
||||||
|
void syscall_kill_self();
|
||||||
|
|
||||||
#endif //NEW_KERNEL_SYSCALL_H
|
#endif //NEW_KERNEL_SYSCALL_H
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
// retrieved from https://github.com/blanham/liballoc
|
// retrieved from https://github.com/blanham/liballoc
|
||||||
#include <sys/types.h>
|
#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);
|
void *realloc(void *, size_t);
|
||||||
|
|
||||||
|
|||||||
@@ -19,15 +19,15 @@ void task_start_first();
|
|||||||
|
|
||||||
void task_switch_next();
|
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();
|
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();
|
void task_lock_acquire();
|
||||||
|
|
||||||
@@ -35,4 +35,6 @@ void task_ensure_enabled();
|
|||||||
|
|
||||||
void task_lock_free();
|
void task_lock_free();
|
||||||
|
|
||||||
|
void task_print_all();
|
||||||
|
|
||||||
#endif //NEW_KERNEL_TASK_H
|
#endif //NEW_KERNEL_TASK_H
|
||||||
|
|||||||
30
include/myke/util/init.h
Normal file
30
include/myke/util/init.h
Normal 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
|
||||||
10
include/myke/util/slingurl.h
Normal file
10
include/myke/util/slingurl.h
Normal 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
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <myke/driver.h>
|
#include <myke/driver.h>
|
||||||
|
|
||||||
|
#define BLOCK_DEV_LBA_SIZE 512
|
||||||
|
|
||||||
#define BLOCK_DEV_ACCESS_OK 0
|
#define BLOCK_DEV_ACCESS_OK 0
|
||||||
#define BLOCK_DEV_ACCESS_ERR 1
|
#define BLOCK_DEV_ACCESS_ERR 1
|
||||||
|
|
||||||
@@ -27,21 +29,21 @@
|
|||||||
|
|
||||||
typedef struct block_device block_device_t;
|
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,
|
typedef uint8_t (*block_device_access)(const block_device_t *device, uint8_t direction, uint32_t lba, uint8_t sectors,
|
||||||
void *target);
|
void *target);
|
||||||
|
|
||||||
struct block_dev_driver {
|
typedef struct block_dev_driver {
|
||||||
char name[16];
|
char name[16];
|
||||||
struct {
|
struct {
|
||||||
uint8_t partitioning: 1;
|
uint8_t partitioning: 1;
|
||||||
} flags;
|
} flags;
|
||||||
block_device_driver_check_device check_device;
|
block_device_driver_check_device check_device;
|
||||||
block_device_driver_free free_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)
|
#define BLOCK_DEV_DRIVER(order) GENERIC_DRIVER(block_dev_driver, order)
|
||||||
|
|
||||||
@@ -59,6 +61,7 @@ struct block_device {
|
|||||||
block_device_access access;
|
block_device_access access;
|
||||||
struct block_dev_driver *driver;
|
struct block_dev_driver *driver;
|
||||||
void *device_info; // pointer to driver defined structure
|
void *device_info; // pointer to driver defined structure
|
||||||
|
void *driver_info; // pointer to driver defined structure
|
||||||
// todo device info
|
// 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_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();
|
void block_dev_print_info();
|
||||||
|
|
||||||
bool block_dev_mount(char *identifier, char *driver);
|
|
||||||
|
|
||||||
#endif //NEW_KERNEL_BLOCKDEV_H
|
#endif //NEW_KERNEL_BLOCKDEV_H
|
||||||
223
include/myke/vfs/lfs/ext2.h
Normal file
223
include/myke/vfs/lfs/ext2.h
Normal 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
|
||||||
36
include/myke/vfs/vfs-driver.h
Normal file
36
include/myke/vfs/vfs-driver.h
Normal 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
70
include/myke/vfs/vfs.h
Normal 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
|
||||||
@@ -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__ */
|
|
||||||
@@ -24,7 +24,7 @@ void fflush(FILE *);
|
|||||||
|
|
||||||
FILE *fopen(const char *, const char *);
|
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 *);
|
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 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
|
#endif //NEW_KERNEL_STDIO_H
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ int atexit(void (*)(void));
|
|||||||
|
|
||||||
int atoi(const char *);
|
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 *);
|
char *getenv(const char *);
|
||||||
|
|
||||||
|
|||||||
@@ -7,23 +7,31 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#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);
|
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 memcmp(const void *s1, const void *s2, size_t n);
|
||||||
|
|
||||||
int strcmp(const char *s1, const char *s2);
|
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);
|
char *strcat(char *dest, const char *src);
|
||||||
|
|
||||||
|
|||||||
@@ -7,5 +7,6 @@
|
|||||||
|
|
||||||
#define MIN(a, b) (((a)<(b))?(a):(b))
|
#define MIN(a, b) (((a)<(b))?(a):(b))
|
||||||
#define MAX(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
|
#endif //NEW_KERNEL_PARAM_H
|
||||||
|
|||||||
50
include/sys/stat.h
Normal file
50
include/sys/stat.h
Normal 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
|
||||||
@@ -5,4 +5,10 @@
|
|||||||
#ifndef NEW_KERNEL_TIME_H
|
#ifndef NEW_KERNEL_TIME_H
|
||||||
#define 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
|
#endif //NEW_KERNEL_TIME_H
|
||||||
|
|||||||
284
kernel/acpi/acpi.c
Normal file
284
kernel/acpi/acpi.c
Normal 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,
|
||||||
|
};
|
||||||
@@ -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
80
kernel/acpi/lailayer.c
Normal 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
|
||||||
|
}
|
||||||
127
kernel/command.c
127
kernel/command.c
@@ -1,6 +1,7 @@
|
|||||||
//
|
//
|
||||||
// Created by rick on 23-02-21.
|
// Created by rick on 23-02-21.
|
||||||
//
|
//
|
||||||
|
#ifdef ENABLE_K_SHELL
|
||||||
#include <attributes.h>
|
#include <attributes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -9,19 +10,24 @@
|
|||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
|
|
||||||
#include <myke/command.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/ide.h>
|
||||||
#include <myke/drivers/pci/pci.h>
|
#include <myke/drivers/pci/pci.h>
|
||||||
#include <myke/fs/blockdev.h>
|
#include <myke/vfs/blockdev.h>
|
||||||
#include <myke/fs/mbr.h>
|
#include <myke/vfs/part/mbr.h>
|
||||||
#include <myke/libk/libk.h>
|
#include <myke/libk/libk.h>
|
||||||
#include <myke/mem/malloc.h>
|
#include <myke/mem/malloc.h>
|
||||||
#include <myke/mem/mem.h>
|
#include <myke/mem/mem.h>
|
||||||
|
#include <myke/tasks/task.h>
|
||||||
#include <myke/util/power.h>
|
#include <myke/util/power.h>
|
||||||
|
#include <myke/vfs/vfs.h>
|
||||||
|
|
||||||
#ifdef ENABLE_SELF_TEST
|
#ifdef ENABLE_SELF_TEST
|
||||||
|
|
||||||
#include <myke/debug/debug.h>
|
#include <myke/debug/debug.h>
|
||||||
|
#include <myke/util/slingurl.h>
|
||||||
|
#include <myke/libk/syscall.h>
|
||||||
|
#include <myke/util/init.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -48,14 +54,26 @@ void help(const char *args);
|
|||||||
|
|
||||||
void shutdown(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
|
#ifdef ENABLE_SELF_TEST
|
||||||
|
|
||||||
|
void explode(const char *args);
|
||||||
|
|
||||||
|
void kill_self(const char *args);
|
||||||
|
|
||||||
void exec_self_test(const char *args);
|
void exec_self_test(const char *args);
|
||||||
|
|
||||||
void smash(const char *args);
|
void smash(const char *args);
|
||||||
|
|
||||||
|
void slingurl(const char *args);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cmd_handler cmd_handlers[] = {
|
cmd_handler cmd_handlers[] = {
|
||||||
@@ -64,35 +82,59 @@ cmd_handler cmd_handlers[] = {
|
|||||||
{"print", print},
|
{"print", print},
|
||||||
{"ide", ide},
|
{"ide", ide},
|
||||||
{"shutdown", shutdown},
|
{"shutdown", shutdown},
|
||||||
{"explode", explode},
|
{"ps", ps},
|
||||||
|
{"mount", mount},
|
||||||
|
{"ls", ls},
|
||||||
|
{"cat", cat},
|
||||||
#ifdef ENABLE_SELF_TEST
|
#ifdef ENABLE_SELF_TEST
|
||||||
|
{"slingurl", slingurl},
|
||||||
|
{"kill-self", kill_self},
|
||||||
{"self-test", exec_self_test},
|
{"self-test", exec_self_test},
|
||||||
{"smash", smash},
|
{"smash", smash},
|
||||||
|
{"explode", explode},
|
||||||
#endif
|
#endif
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef ENABLE_SELF_TEST
|
||||||
|
|
||||||
|
void slingurl(const char *args) {
|
||||||
|
slingurl_decompose(args);
|
||||||
|
}
|
||||||
|
|
||||||
void smash(const char *args) {
|
void smash(const char *args) {
|
||||||
|
// smash the stack, should trigger the stack protector
|
||||||
char data[16];
|
char data[16];
|
||||||
memset(data, 'A', 32);
|
memset(data, 'A', 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kill_self(const char *args) {
|
||||||
|
syscall_kill_self();
|
||||||
|
}
|
||||||
|
|
||||||
void exec_self_test(const char *args) {
|
void exec_self_test(const char *args) {
|
||||||
|
// unit tests
|
||||||
self_test();
|
self_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void explode(const char *args) {
|
void explode(const char *args) {
|
||||||
|
// trigger a divide by zero exception
|
||||||
uint32_t x = 0;
|
uint32_t x = 0;
|
||||||
uint32_t y = 0;
|
uint32_t y = 0;
|
||||||
__asm__("div %%ebx" :
|
__asm__("div %%ebx" :
|
||||||
"=a" (x), "=b" (y));
|
"=a" (x), "=b" (y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void shutdown(const char *args) {
|
void shutdown(const char *args) {
|
||||||
power_shutdown();
|
power_shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ps(const char *args) {
|
||||||
|
task_print_all();
|
||||||
|
}
|
||||||
|
|
||||||
void print_bootinfo() {
|
void print_bootinfo() {
|
||||||
printf("Bootloader name: %s\n"
|
printf("Bootloader name: %s\n"
|
||||||
"cmdline: %s\n",
|
"cmdline: %s\n",
|
||||||
@@ -154,17 +196,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) {
|
void store_bootloader_info(multiboot_info_t *multiboot_info) {
|
||||||
// get bootloader and cmdline
|
// get bootloader and cmdline
|
||||||
if (multiboot_info->flags & MULTIBOOT_INFO_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) {
|
if (cmdline_length > CMDLINE_MAX_LENGTH) {
|
||||||
k_panics("cmdline to long!\n");
|
k_panics("cmdline to long!\n");
|
||||||
}
|
}
|
||||||
memcpy(cmdline, (char *) multiboot_info->cmdline, cmdline_length);
|
memcpy(cmdline, (char *) multiboot_info->cmdline, cmdline_length);
|
||||||
}
|
}
|
||||||
if (multiboot_info->flags & MULTIBOOT_INFO_BOOT_LOADER_NAME) {
|
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) {
|
if (bootloader_length > BOOTLOADER_NAME_MAX_LENGTH) {
|
||||||
k_panics("bootloader name to long!\n");
|
k_panics("bootloader name to long!\n");
|
||||||
}
|
}
|
||||||
@@ -193,3 +292,15 @@ void att_noreturn main_loop(void *data) {
|
|||||||
free(msg);
|
free(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
@@ -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() {
|
void cpuidx_print_info() {
|
||||||
union cpu_name name;
|
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;
|
name.end = 0;
|
||||||
printf("CPU: %s\n", &name.name);
|
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("");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,11 @@
|
|||||||
#include <myke/cpu/isr.h>
|
#include <myke/cpu/isr.h>
|
||||||
#include <myke/debug/debug.h>
|
#include <myke/debug/debug.h>
|
||||||
#include <myke/cpu/idt.h>
|
#include <myke/cpu/idt.h>
|
||||||
|
#include <myke/cpu/pic.h>
|
||||||
#include <myke/cpu/syscall_handler.h>
|
#include <myke/cpu/syscall_handler.h>
|
||||||
#include <myke/drivers/ports.h>
|
|
||||||
#include <myke/libk/libk.h>
|
#include <myke/libk/libk.h>
|
||||||
#include <myke/tasks/task.h>
|
#include <myke/tasks/task.h>
|
||||||
|
|
||||||
#define PIC_END_OF_INTERRUPT 0x20
|
|
||||||
|
|
||||||
isr_t interrupt_handlers[256];
|
isr_t interrupt_handlers[256];
|
||||||
|
|
||||||
void isr_install() {
|
void isr_install() {
|
||||||
@@ -51,20 +49,10 @@ void isr_install() {
|
|||||||
set_idt_gate(31, (uint32_t) isr31);
|
set_idt_gate(31, (uint32_t) isr31);
|
||||||
|
|
||||||
// Remap the PIC
|
// Remap the PIC
|
||||||
// todo make readable
|
pic_init(IRQ0);
|
||||||
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);
|
|
||||||
|
|
||||||
// Install the IRQs
|
// 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(33, (uint32_t) irq1);
|
||||||
set_idt_gate(34, (uint32_t) irq2);
|
set_idt_gate(34, (uint32_t) irq2);
|
||||||
set_idt_gate(35, (uint32_t) irq3);
|
set_idt_gate(35, (uint32_t) irq3);
|
||||||
@@ -72,7 +60,7 @@ void isr_install() {
|
|||||||
set_idt_gate(37, (uint32_t) irq5);
|
set_idt_gate(37, (uint32_t) irq5);
|
||||||
set_idt_gate(38, (uint32_t) irq6);
|
set_idt_gate(38, (uint32_t) irq6);
|
||||||
set_idt_gate(39, (uint32_t) irq7);
|
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(41, (uint32_t) irq9);
|
||||||
set_idt_gate(42, (uint32_t) irq10);
|
set_idt_gate(42, (uint32_t) irq10);
|
||||||
set_idt_gate(43, (uint32_t) irq11);
|
set_idt_gate(43, (uint32_t) irq11);
|
||||||
@@ -81,6 +69,7 @@ void isr_install() {
|
|||||||
set_idt_gate(46, (uint32_t) irq14);
|
set_idt_gate(46, (uint32_t) irq14);
|
||||||
set_idt_gate(47, (uint32_t) irq15);
|
set_idt_gate(47, (uint32_t) irq15);
|
||||||
|
|
||||||
|
// 0x80 SYSCALL
|
||||||
set_idt_gate(128, (uint32_t) isr128);
|
set_idt_gate(128, (uint32_t) isr128);
|
||||||
|
|
||||||
set_idt(); // Load with ASM
|
set_idt(); // Load with ASM
|
||||||
@@ -124,7 +113,7 @@ char *exception_messages[] = {
|
|||||||
"Reserved"
|
"Reserved"
|
||||||
};
|
};
|
||||||
|
|
||||||
void isr_handler(isr_registers_t r) {
|
void att_used isr_handler(isr_registers_t r) {
|
||||||
char msg[256];
|
char msg[256];
|
||||||
if (r.int_no == 128) {
|
if (r.int_no == 128) {
|
||||||
syscall_handle(&r);
|
syscall_handle(&r);
|
||||||
@@ -139,11 +128,10 @@ void register_interrupt_handler(uint8_t n, isr_t handler) {
|
|||||||
interrupt_handlers[n] = 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
|
/* After every interrupt we need to send an EOI to the PICs
|
||||||
* or they will not send another interrupt again */
|
* 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 */
|
pic_eoi(r.int_no >= IRQ8);
|
||||||
port_byte_out(PORT_PIC_MASTER_COMMAND, PIC_END_OF_INTERRUPT); /* master */
|
|
||||||
|
|
||||||
if (r.int_no >= IRQ0 && r.int_no < IRQ15) {
|
if (r.int_no >= IRQ0 && r.int_no < IRQ15) {
|
||||||
task_notify_irq(r.int_no - IRQ0);
|
task_notify_irq(r.int_no - IRQ0);
|
||||||
|
|||||||
30
kernel/cpu/lapic.c
Normal file
30
kernel/cpu/lapic.c
Normal 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
51
kernel/cpu/pic.c
Normal 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 */
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <myke/cpu/timer.h>
|
#include <myke/cpu/pit.h>
|
||||||
#include <myke/drivers/ports.h>
|
#include <myke/drivers/ports.h>
|
||||||
#include <myke/cpu/isr.h>
|
#include <myke/cpu/isr.h>
|
||||||
#include <myke/libk/libk.h>
|
#include <myke/libk/libk.h>
|
||||||
@@ -33,19 +33,37 @@
|
|||||||
#define PIT_CHANNEL_1 (0b01 << 6)
|
#define PIT_CHANNEL_1 (0b01 << 6)
|
||||||
#define PIT_CHANNEL_2 (0b10 << 6)
|
#define PIT_CHANNEL_2 (0b10 << 6)
|
||||||
#define PIT_CHANNEL_READ_BACK (0b11 << 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;
|
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++;
|
tick++;
|
||||||
task_switch_next();
|
task_switch_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t timer_get_tick() {
|
uint32_t pit_get_tick() {
|
||||||
return tick;
|
return tick;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sleep(uint32_t milliseconds) {
|
void pit_sleep(uint32_t milliseconds) {
|
||||||
uint32_t done = tick + milliseconds;
|
uint32_t done = tick + milliseconds;
|
||||||
while (tick != done) {
|
while (tick != done) {
|
||||||
k_wait_for_interrupt();
|
k_wait_for_interrupt();
|
||||||
@@ -60,10 +78,10 @@ void print_current_tick() {
|
|||||||
kprint("\n");
|
kprint("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int init_timer(uint32_t freq) {
|
int pit_int_frequency(uint32_t freq) {
|
||||||
register_interrupt_handler(IRQ0, timer_callback);
|
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 low = (uint8_t) (divisor & 0xFF);
|
||||||
uint8_t high = (uint8_t) ((divisor >> 8) & 0xFF);
|
uint8_t high = (uint8_t) ((divisor >> 8) & 0xFF);
|
||||||
port_byte_out(PORT_PIT_COMMAND,
|
port_byte_out(PORT_PIT_COMMAND,
|
||||||
@@ -72,3 +90,21 @@ int init_timer(uint32_t freq) {
|
|||||||
port_byte_out(PORT_PIT_DATA_0, high);
|
port_byte_out(PORT_PIT_DATA_0, high);
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
@@ -23,6 +23,11 @@ void syscall_handle(isr_registers_t *registers) {
|
|||||||
task_ensure_enabled();
|
task_ensure_enabled();
|
||||||
task_suspend();
|
task_suspend();
|
||||||
break;
|
break;
|
||||||
|
case SYSCALL_KILL_SELF:
|
||||||
|
task_ensure_enabled();
|
||||||
|
task_end(task_get_current_tid());
|
||||||
|
task_switch_next();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ static const char *elf_name_strtab = ".strtab";
|
|||||||
|
|
||||||
struct stackframe {
|
struct stackframe {
|
||||||
struct stackframe *ebp;
|
struct stackframe *ebp;
|
||||||
uint32_t eip;
|
uintptr_t eip;
|
||||||
};
|
};
|
||||||
|
|
||||||
char *debug_get_shstrtab_entry(uint32_t ndx) {
|
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);
|
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) {
|
if (elf_symtab == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -106,9 +106,9 @@ void debug_backtrace(bool do_sync) {
|
|||||||
while (frame->ebp != NULL) {
|
while (frame->ebp != NULL) {
|
||||||
struct elf32_symtab_entry *entry = debug_get_entry_for_addr(frame->eip);
|
struct elf32_symtab_entry *entry = debug_get_entry_for_addr(frame->eip);
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
sprintf(msg, "#unknown (%x)\n", frame->eip);
|
sprintf(msg, "#unknown (%lx)\n", frame->eip);
|
||||||
} else {
|
} 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);
|
printer(msg);
|
||||||
frame = frame->ebp;
|
frame = frame->ebp;
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ void test_string() {
|
|||||||
const char *strcpy_src_test = "abc\0def";
|
const char *strcpy_src_test = "abc\0def";
|
||||||
char *strcpy_dst_test = "\0\0\0\0\0\0\0";
|
char *strcpy_dst_test = "\0\0\0\0\0\0\0";
|
||||||
const char *strcpy_expected_test = "abc\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 push
|
||||||
#pragma clang diagnostic ignored "-Wpointer-sign"
|
#pragma clang diagnostic ignored "-Wpointer-sign"
|
||||||
assert_array_equal(strcpy_dst_test, strcpy_expected_test, 8);
|
assert_array_equal(strcpy_dst_test, strcpy_expected_test, 8);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <myke/libc/ringqueue.h>
|
#include <myke/libc/ringqueue.h>
|
||||||
#include <myke/libk/libk.h>
|
#include <myke/libk/libk.h>
|
||||||
#include <myke/libk/syscall.h>
|
#include <myke/libk/syscall.h>
|
||||||
|
#include <myke/util/init.h>
|
||||||
|
|
||||||
|
|
||||||
const char scancode_map_lowercase[] = {
|
const char scancode_map_lowercase[] = {
|
||||||
@@ -131,7 +132,7 @@ static void keyboard_callback(isr_registers_t *regs) {
|
|||||||
publish_key_event(scancode);
|
publish_key_event(scancode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_keyboard() {
|
void keyboard_init() {
|
||||||
register_interrupt_handler(IRQ1, keyboard_callback);
|
register_interrupt_handler(IRQ1, keyboard_callback);
|
||||||
keyboard_state.shift = 0;
|
keyboard_state.shift = 0;
|
||||||
keyboard_state.ctrl = 0;
|
keyboard_state.ctrl = 0;
|
||||||
@@ -139,3 +140,9 @@ void init_keyboard() {
|
|||||||
keyboard_state.extended = 0;
|
keyboard_state.extended = 0;
|
||||||
keyboard_event_buffer = create_buffer(256, sizeof(KeyEvent));
|
keyboard_event_buffer = create_buffer(256, sizeof(KeyEvent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INIT_FUNCTION(100) = {
|
||||||
|
.name = "keyboard",
|
||||||
|
.stage = INIT_STAGE_LATE_BOOT,
|
||||||
|
.init = keyboard_init,
|
||||||
|
};
|
||||||
@@ -9,12 +9,12 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <myke/cpu/timer.h>
|
#include <myke/cpu/pit.h>
|
||||||
#include <myke/debug/debug.h>
|
#include <myke/debug/debug.h>
|
||||||
#include <myke/drivers/pci/ide.h>
|
#include <myke/drivers/pci/ide.h>
|
||||||
#include <myke/drivers/pci/pci.h>
|
#include <myke/drivers/pci/pci.h>
|
||||||
#include <myke/drivers/ports.h>
|
#include <myke/drivers/ports.h>
|
||||||
#include <myke/fs/blockdev.h>
|
#include <myke/vfs/blockdev.h>
|
||||||
#include <myke/libk/kprint.h>
|
#include <myke/libk/kprint.h>
|
||||||
#include <myke/libk/libk.h>
|
#include <myke/libk/libk.h>
|
||||||
#include <myke/tasks/locking.h>
|
#include <myke/tasks/locking.h>
|
||||||
@@ -395,6 +395,10 @@ void ide_register_block_devices() {
|
|||||||
if (!ide_devices[i].reserved) {
|
if (!ide_devices[i].reserved) {
|
||||||
continue;
|
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
|
ide_block_device_info *info = malloc(sizeof(ide_block_device_info)); // todo free for this one
|
||||||
info->device_number = i;
|
info->device_number = i;
|
||||||
@@ -451,11 +455,11 @@ uint8_t att_used ide_pci_initialize(pci_device *device) {
|
|||||||
|
|
||||||
// (I) Select Drive:
|
// (I) Select Drive:
|
||||||
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // 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:
|
// (II) Send ATA Identify Command:
|
||||||
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
|
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.
|
// it is based on System Timer Device Driver.
|
||||||
|
|
||||||
// (III) Polling:
|
// (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);
|
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
|
||||||
sleep(1);
|
pit_sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// (V) Read Identification Space of the Device:
|
// (V) Read Identification Space of the Device:
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
// Created by rick on 28-01-21.
|
// Created by rick on 28-01-21.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <myke/drivers/serial.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <myke/drivers/ports.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_DATA_AVAILABLE (1 << 0)
|
||||||
#define SERIAL_INTERRUPT_TRANSMITTER_EMPTY (1 << 1)
|
#define SERIAL_INTERRUPT_TRANSMITTER_EMPTY (1 << 1)
|
||||||
@@ -51,7 +52,7 @@
|
|||||||
#define MODEM_CONTROL_LOOPBACK_MODE (1 << 4)
|
#define MODEM_CONTROL_LOOPBACK_MODE (1 << 4)
|
||||||
#define MODEM_CONTROL_AUTOFLOW_CONTROL_ENABLED (1 << 5)
|
#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_INTERRUPT, 0); // Disable all interrupts
|
||||||
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_LINE_CONTROL,
|
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_LINE_CONTROL,
|
||||||
LINE_CONTROL_DIVISOR); // Enable DLAB (set baud rate divisor)
|
LINE_CONTROL_DIVISOR); // Enable DLAB (set baud rate divisor)
|
||||||
@@ -114,4 +115,17 @@ void serial_kprint(const char *msg) {
|
|||||||
write_serial(c);
|
write_serial(c);
|
||||||
i++;
|
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,
|
||||||
|
};
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <myke/drivers/vgascreen.h>
|
|
||||||
|
|
||||||
#include <myke/drivers/ports.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;
|
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) {
|
int get_offset_col(int offset) {
|
||||||
return (offset - (get_offset_row(offset) * 2 * VGA_COL_MAX)) / 2;
|
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,
|
||||||
|
};
|
||||||
@@ -4,22 +4,17 @@
|
|||||||
|
|
||||||
#define DEBUG_INIT
|
#define DEBUG_INIT
|
||||||
|
|
||||||
#include <myke/acpi.h>
|
|
||||||
#include <myke/command.h>
|
#include <myke/command.h>
|
||||||
#include <myke/cpu/cpuidx.h>
|
|
||||||
#include <myke/cpu/gdt.h>
|
#include <myke/cpu/gdt.h>
|
||||||
#include <myke/cpu/isr.h>
|
#include <myke/cpu/isr.h>
|
||||||
#include <myke/cpu/timer.h>
|
#include <myke/cpu/pit.h>
|
||||||
#include <myke/debug/debug.h>
|
#include <myke/debug/debug.h>
|
||||||
#include <myke/drivers/keyboard.h>
|
|
||||||
#include <myke/drivers/pci/pci.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/kprint.h>
|
||||||
#include <myke/libk/libk.h>
|
#include <myke/libk/libk.h>
|
||||||
#include <myke/libk/syscall.h>
|
#include <myke/libk/syscall.h>
|
||||||
#include <myke/mem/mem.h>
|
#include <myke/mem/mem.h>
|
||||||
|
#include <myke/util/init.h>
|
||||||
#include <myke/tasks/task.h>
|
#include <myke/tasks/task.h>
|
||||||
|
|
||||||
const int version_major = 0,
|
const int version_major = 0,
|
||||||
@@ -43,11 +38,8 @@ void init_pci_system() {
|
|||||||
void att_noreturn att_used kmain(multiboot_info_t *multiboot_info, uint32_t mb_name) {
|
void att_noreturn att_used kmain(multiboot_info_t *multiboot_info, uint32_t mb_name) {
|
||||||
// early init
|
// early init
|
||||||
isr_install();
|
isr_install();
|
||||||
vga_clear_screen();
|
// initialize early modules (kprint etc.)
|
||||||
vga_clear_screen(' ', VGA_WHITE | (VGA_GRAY << VGA_SHIFT_BG));
|
init_execute_all(INIT_STAGE_EARLY_BOOT_0);
|
||||||
kprint_register(vga_kprint);
|
|
||||||
serial_init();
|
|
||||||
kprint_register(serial_kprint);
|
|
||||||
|
|
||||||
// parse multiboot
|
// parse multiboot
|
||||||
if (mb_name != MULTIBOOT_BOOTLOADER_MAGIC) {
|
if (mb_name != MULTIBOOT_BOOTLOADER_MAGIC) {
|
||||||
@@ -58,35 +50,33 @@ void att_noreturn att_used kmain(multiboot_info_t *multiboot_info, uint32_t mb_n
|
|||||||
|
|
||||||
// initialize memory management
|
// initialize memory management
|
||||||
init_mmap(multiboot_info);
|
init_mmap(multiboot_info);
|
||||||
|
// safe multiboot info for later use
|
||||||
|
debug_store_info(multiboot_info);
|
||||||
|
|
||||||
gdt_init();
|
gdt_init();
|
||||||
|
|
||||||
// initialize kprint functionality
|
// initialize kprint functionality
|
||||||
kprint_init();
|
kprint_init();
|
||||||
|
// initialize early driver code (ACPI, etc.)
|
||||||
debug_store_info(multiboot_info);
|
init_execute_all(INIT_STAGE_EARLY_BOOT_1);
|
||||||
|
|
||||||
// identify cpu
|
|
||||||
cpuidx_print_info();
|
|
||||||
|
|
||||||
// enable interrupts
|
// enable interrupts
|
||||||
__asm__ __volatile__("sti");
|
__asm__ __volatile__("sti");
|
||||||
// start the timer
|
// start the timer
|
||||||
init_timer(1000);
|
pit_int_frequency(1000);
|
||||||
// initialize devices
|
|
||||||
init_keyboard();
|
// initialize drivers that are not discovered in any other way
|
||||||
|
init_execute_all(INIT_STAGE_LATE_BOOT);
|
||||||
|
|
||||||
|
// init PCI
|
||||||
init_pci_system();
|
init_pci_system();
|
||||||
|
|
||||||
printf("Booted successfully v%d.%d.%d\n", version_major, version_minor, version_patch);
|
printf("Booted successfully v%d.%d.%d\n", version_major, version_minor, version_patch);
|
||||||
|
|
||||||
// initialize tasking
|
// initialize tasking
|
||||||
task_init();
|
task_init();
|
||||||
kprint_start_task();
|
// let other system provide tasks (command, kprint, blockdev)
|
||||||
block_dev_start_task();
|
init_execute_all(INIT_STAGE_PRE_TASKING);
|
||||||
#ifdef K_SHELL
|
|
||||||
task_spawn(main_loop, NULL);
|
|
||||||
#endif
|
|
||||||
acpi_init_task();
|
|
||||||
// switch to tasking
|
// switch to tasking
|
||||||
syscall_start_scheduler();
|
syscall_start_scheduler();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,11 @@ uint32_t vasprintf(char *buf, const char *fmt, va_list args) {
|
|||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int l = 0;
|
||||||
|
while (fmt[i] == 'l') {
|
||||||
|
l++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
switch (fmt[i]) {
|
switch (fmt[i]) {
|
||||||
case 's': { // string
|
case 's': { // string
|
||||||
uint32_t j = 0;
|
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);
|
buf[ptr++] = (char) va_arg(args, int);
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
|
case 'p':
|
||||||
case 'X': // todo capitalize
|
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;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
case 'd':
|
case 'd':
|
||||||
|
|||||||
@@ -43,24 +43,21 @@ char *reverse(char *buffer, int i, int j) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Iterative function to implement itoa() function in C
|
// 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
|
// invalid input
|
||||||
if (base < 2 || base > 32)
|
if (base < 2 || base > 32)
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
||||||
// consider absolute value of number
|
|
||||||
int n = abs(value);
|
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (n) {
|
while (value) {
|
||||||
int r = n % base;
|
uint32_t r = value % base;
|
||||||
|
|
||||||
if (r >= 10)
|
if (r >= 10)
|
||||||
buffer[i++] = 65 + (r - 10);
|
buffer[i++] = 65 + (r - 10);
|
||||||
else
|
else
|
||||||
buffer[i++] = 48 + r;
|
buffer[i++] = 48 + r;
|
||||||
|
|
||||||
n = n / base;
|
value = value / base;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if number is 0
|
// if number is 0
|
||||||
|
|||||||
@@ -5,27 +5,37 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/types.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++) {
|
for (size_t i = 0; i < amount; i++) {
|
||||||
((char *) dst)[i] = ((const char *) src)[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) {
|
for (size_t i = 0; i < amount; ++i) {
|
||||||
((char *) dst)[i] = (char) data;
|
((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);
|
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);
|
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 strcmp(const char *s1, const char *s2) {
|
||||||
int len1 = strlen(s1);
|
size_t len1 = strlen(s1);
|
||||||
int len2 = strlen(s2);
|
size_t len2 = strlen(s2);
|
||||||
return strncmp(s1, s2, MAX(len1, len2));
|
return strncmp(s1, s2, MAX(len1, len2));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *strchr(const char *s, char c) {
|
char *strchr(const char *s, char c) {
|
||||||
int index = 0;
|
size_t index = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (s[index] == c) {
|
if (s[index] == c) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
|
||||||
return &s[index];
|
return &s[index];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
if (s[index] == 0) {
|
if (s[index] == 0) {
|
||||||
return NULL;
|
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) {
|
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||||
uint8_t a, b;
|
uint8_t a, b;
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
a = ((uint8_t *) s1)[i];
|
a = ((uint8_t *) s1)[i];
|
||||||
b = ((uint8_t *) s2)[i];
|
b = ((uint8_t *) s2)[i];
|
||||||
if (a > b) return 1;
|
if (a > b) return 1;
|
||||||
if (b < a) return -1;
|
if (a < b) return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int strncmp(const char *s1, const char *s2, int n) {
|
int strncmp(const char *s1, const char *s2, size_t n) {
|
||||||
for (int i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
if (s1[i] == 0 && s2[i] == 0) {
|
if (s1[i] == 0 && s2[i] == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -105,3 +134,14 @@ char *strncat(char *dest, const char *src, size_t n) {
|
|||||||
}
|
}
|
||||||
return dest;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,12 +9,13 @@
|
|||||||
#include <myke/libk/kprint.h>
|
#include <myke/libk/kprint.h>
|
||||||
#include <myke/tasks/task.h>
|
#include <myke/tasks/task.h>
|
||||||
#include <myke/util/stream.h>
|
#include <myke/util/stream.h>
|
||||||
|
#include <myke/util/init.h>
|
||||||
|
|
||||||
#define MAX_HANDLERS 8
|
#define MAX_HANDLERS 8
|
||||||
#define STREAM_SIZE (32*1024)
|
#define STREAM_SIZE (32*1024)
|
||||||
#define PRINT_BUFFER_SIZE 64
|
#define PRINT_BUFFER_SIZE 64
|
||||||
|
|
||||||
stream_t *kprint_stream;
|
stream_t *kprint_stream = NULL;
|
||||||
|
|
||||||
kprint_handler handlers[MAX_HANDLERS] = {0};
|
kprint_handler handlers[MAX_HANDLERS] = {0};
|
||||||
|
|
||||||
@@ -29,7 +30,11 @@ void kprint_register(kprint_handler handler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void kprint(const char *msg) {
|
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) {
|
void kprint_internal(const char *msg) {
|
||||||
@@ -64,5 +69,11 @@ void att_noreturn kprint_task(void *_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void kprint_start_task() {
|
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,
|
||||||
|
};
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ void att_noreturn k_panics(const char *msg) {
|
|||||||
k_panic();
|
k_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void att_noreturn k_not_implemented() {
|
||||||
|
k_panics("Not Implemented");
|
||||||
|
}
|
||||||
|
|
||||||
void att_noreturn k_panic() {
|
void att_noreturn k_panic() {
|
||||||
kprint_sync("PANIC!");
|
kprint_sync("PANIC!");
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|||||||
@@ -35,3 +35,7 @@ void syscall_yield_irq(uint16_t irq) {
|
|||||||
void syscall_job_suspend() {
|
void syscall_job_suspend() {
|
||||||
syscall1(SYSCALL_SUSPEND);
|
syscall1(SYSCALL_SUSPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void syscall_kill_self() {
|
||||||
|
syscall1(SYSCALL_KILL_SELF);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
int startedBet = 0;
|
||||||
unsigned long long bestSize = 0;
|
unsigned long long bestSize = 0;
|
||||||
void *p = NULL;
|
void *p = NULL;
|
||||||
@@ -725,7 +725,7 @@ void free(void *ptr) {
|
|||||||
|
|
||||||
|
|
||||||
void *calloc(size_t nobj, size_t size) {
|
void *calloc(size_t nobj, size_t size) {
|
||||||
int real_size;
|
size_t real_size;
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
real_size = nobj * size;
|
real_size = nobj * size;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// Created by rick on 22-04-20.
|
// Created by rick on 22-04-20.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <attributes.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@@ -22,10 +21,10 @@
|
|||||||
#define MMAP_TYPE_PAGING 7
|
#define MMAP_TYPE_PAGING 7
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t address;
|
uintptr_t address;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
} att_packed mmap_entry;
|
} mmap_entry;
|
||||||
|
|
||||||
int last_memmap_entry = 0;
|
int last_memmap_entry = 0;
|
||||||
mmap_entry memmap[MEMMAP_ENTRIES] = {
|
mmap_entry memmap[MEMMAP_ENTRIES] = {
|
||||||
@@ -49,7 +48,7 @@ mmap_entry memmap[MEMMAP_ENTRIES] = {
|
|||||||
|
|
||||||
void use_mmap_entry(struct multiboot_mmap_entry *entry) {
|
void use_mmap_entry(struct multiboot_mmap_entry *entry) {
|
||||||
mmap_entry *mm_entry = &memmap[last_memmap_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->length = entry->len;
|
||||||
mm_entry->type = entry->type;
|
mm_entry->type = entry->type;
|
||||||
// check if the entry overlaps with the kernel address space
|
// check if the entry overlaps with the kernel address space
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <myke/libk/syscall.h>
|
#include <myke/libk/syscall.h>
|
||||||
|
|
||||||
typedef struct lock_fifo_entry {
|
typedef struct lock_fifo_entry {
|
||||||
uint32_t tid;
|
pid_t tid;
|
||||||
struct lock_fifo_entry *next;
|
struct lock_fifo_entry *next;
|
||||||
} lock_fifo_entry_t;
|
} lock_fifo_entry_t;
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,14 @@
|
|||||||
|
|
||||||
#include <attributes.h>
|
#include <attributes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <myke/cpu/cpu.h>
|
#include <myke/cpu/cpu.h>
|
||||||
#include <myke/libk/libk.h>
|
#include <myke/libk/libk.h>
|
||||||
#include <myke/mem/pmm.h>
|
#include <myke/mem/pmm.h>
|
||||||
|
#include <myke/libk/syscall.h>
|
||||||
#include <myke/tasks/task.h>
|
#include <myke/tasks/task.h>
|
||||||
|
|
||||||
#define stack_end(task) ((task)->stack + ((task)->stack_page_count * PAGE_SIZE))
|
#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_STOPPED (1 << 6)
|
||||||
#define TASK_STATE_ERROR (1 << 7)
|
#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;
|
int errno = 0;
|
||||||
|
|
||||||
typedef struct task {
|
typedef struct task {
|
||||||
|
// state
|
||||||
bool present: 1;
|
bool present: 1;
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
uint16_t wait_irq;
|
uint16_t wait_irq;
|
||||||
|
|
||||||
uint32_t tid;
|
// identity
|
||||||
|
pid_t tid;
|
||||||
int errno;
|
char *name;
|
||||||
|
|
||||||
|
// linked list
|
||||||
struct task *next;
|
struct task *next;
|
||||||
|
|
||||||
|
// persistence/memory
|
||||||
|
int errno;
|
||||||
void *stack;
|
void *stack;
|
||||||
uint32_t stack_page_count;
|
uint32_t stack_page_count;
|
||||||
|
|
||||||
task_registers_t *task_registers;
|
task_registers_t *task_registers;
|
||||||
} task_t;
|
} task_t;
|
||||||
|
|
||||||
@@ -57,19 +82,23 @@ task_t *first_task = NULL;
|
|||||||
task_t *last_task = NULL;
|
task_t *last_task = NULL;
|
||||||
task_t *current_task = NULL;
|
task_t *current_task = NULL;
|
||||||
|
|
||||||
uint32_t last_tid = 0;
|
pid_t last_tid = 0;
|
||||||
|
|
||||||
extern switch_task(task_registers_t
|
pid_t reaper_pid = 0;
|
||||||
**, task_registers_t*);
|
|
||||||
|
extern void switch_task(task_registers_t **, task_registers_t *);
|
||||||
|
|
||||||
extern att_cdecl att_noreturn void __task_entry_point();
|
extern att_cdecl att_noreturn void __task_entry_point();
|
||||||
|
|
||||||
extern att_noreturn void __task_entry_point_inner();
|
extern att_noreturn void __task_entry_point_inner();
|
||||||
|
|
||||||
|
// internal api
|
||||||
|
void task_free(task_t *task);
|
||||||
|
|
||||||
// explicit cdecl calling convention
|
// 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);
|
entrypoint(entry_data);
|
||||||
// task_end_self();
|
syscall_kill_self();
|
||||||
while (true); // halt
|
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;
|
return current_task->tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_signal(uint32_t tid) {
|
void task_signal(pid_t tid) {
|
||||||
task_t *t = first_task;
|
task_t *t = first_task;
|
||||||
while (t != NULL) {
|
while (t != NULL) {
|
||||||
if (t->tid == tid) {
|
if (t->tid == tid) {
|
||||||
@@ -114,10 +143,47 @@ void task_suspend() {
|
|||||||
task_switch_next();
|
task_switch_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// internal tasks
|
||||||
void att_noreturn task_idle(void *data) {
|
void att_noreturn task_idle(void *data) {
|
||||||
while (true) __asm__("hlt");
|
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) {
|
void task_notify_irq(uint8_t irq_no) {
|
||||||
uint16_t irq__bit = 1 << irq_no;
|
uint16_t irq__bit = 1 << irq_no;
|
||||||
task_t *t = first_task;
|
task_t *t = first_task;
|
||||||
@@ -198,10 +264,11 @@ void task_switch_next() {
|
|||||||
task_switch_next_inner(task_first_runnable());
|
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));
|
task_t *new_task = malloc(sizeof(task_t));
|
||||||
memset((uint8_t *) new_task, 0, sizeof(task_t));
|
memset((uint8_t *) new_task, 0, sizeof(task_t));
|
||||||
new_task->tid = last_tid++;
|
new_task->tid = last_tid++;
|
||||||
|
new_task->name = strdup(name);
|
||||||
new_task->state = TASK_STATE_RUNNABLE;
|
new_task->state = TASK_STATE_RUNNABLE;
|
||||||
|
|
||||||
new_task->stack = pmm_get_pages(16);
|
new_task->stack = pmm_get_pages(16);
|
||||||
@@ -233,12 +300,19 @@ task_t *task_create(task_entrypoint entrypoint, void *entry_data) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_init() {
|
void task_free(task_t *task) {
|
||||||
idle_task = task_create(task_idle, NULL);
|
pmm_free_pages(task->stack, 16);
|
||||||
|
free(task->name);
|
||||||
|
free(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
|
void task_init() {
|
||||||
task_t *new_task = task_create(entrypoint, entry_data);
|
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) {
|
if (first_task == NULL) {
|
||||||
// first task
|
// first task
|
||||||
first_task = new_task;
|
first_task = new_task;
|
||||||
@@ -249,13 +323,27 @@ uint32_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
|
|||||||
return new_task->tid;
|
return new_task->tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_end(uint32_t tid) {
|
void task_end(pid_t tid) {
|
||||||
task_t *t = first_task;
|
task_t *t = first_task;
|
||||||
while (t != NULL) {
|
while (t != NULL) {
|
||||||
if (t->tid == tid) {
|
if (t->tid == tid) {
|
||||||
t->state = TASK_STATE_STOPPED;
|
t->state = TASK_STATE_STOPPED;
|
||||||
|
task_signal(reaper_pid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t = t->next;
|
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
21
kernel/util/init.c
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
#include <attributes.h>
|
#include <attributes.h>
|
||||||
|
|
||||||
#include <myke/drivers/ports.h>
|
#include <lai/helpers/pm.h>
|
||||||
|
|
||||||
#include <myke/libk/libk.h>
|
#include <myke/libk/libk.h>
|
||||||
#include <myke/util/power.h>
|
#include <myke/util/power.h>
|
||||||
|
|
||||||
void att_noreturn power_shutdown() {
|
void att_noreturn power_shutdown() {
|
||||||
port_word_out(PORT_ACPI, PORT_ACPI_SHUTDOWN);
|
lai_enter_sleep(5);
|
||||||
port_word_out(PORT_QEMU_COMMAND, PORT_QEMU_COMMAND_SHUTDOWN);
|
|
||||||
port_word_out(PORT_VBOX, PORT_VBOX_SHUTDOWN);
|
|
||||||
k_panics("Failed to shut down!\n");
|
k_panics("Failed to shut down!\n");
|
||||||
}
|
}
|
||||||
71
kernel/util/slingurl.c
Normal file
71
kernel/util/slingurl.c
Normal 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);
|
||||||
|
}
|
||||||
@@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
#include <attributes.h>
|
#include <attributes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <myke/fs/blockdev.h>
|
#include <myke/vfs/blockdev.h>
|
||||||
#include <myke/libk/libk.h>
|
#include <myke/libk/libk.h>
|
||||||
#include <myke/tasks/locking.h>
|
#include <myke/tasks/locking.h>
|
||||||
#include <myke/tasks/task.h>
|
#include <myke/tasks/task.h>
|
||||||
|
#include <myke/util/init.h>
|
||||||
|
|
||||||
#define MAX_BLOCK_DEVS 64
|
#define MAX_BLOCK_DEVS 64
|
||||||
|
|
||||||
@@ -25,6 +25,25 @@ extern struct block_dev_driver __stop_block_dev_driver[];
|
|||||||
semaphore_t *block_semaphore;
|
semaphore_t *block_semaphore;
|
||||||
bool blockdev_task_running = false;
|
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) {
|
uint8_t block_dev_register(block_device_t *device) {
|
||||||
if (last_block_dev >= MAX_BLOCK_DEVS - 1) {
|
if (last_block_dev >= MAX_BLOCK_DEVS - 1) {
|
||||||
return BLOCK_DEV_REGISTER_FULL;
|
return BLOCK_DEV_REGISTER_FULL;
|
||||||
@@ -38,6 +57,25 @@ uint8_t block_dev_register(block_device_t *device) {
|
|||||||
return BLOCK_DEV_REGISTER_OK;
|
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) {
|
void block_dev_free(block_device_t *device) {
|
||||||
//todo
|
//todo
|
||||||
k_panics("block dev free not supported");
|
k_panics("block dev free not supported");
|
||||||
@@ -51,53 +89,10 @@ int block_dev_num_not_scanned() {
|
|||||||
return 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() {
|
void block_dev_scan() {
|
||||||
int c_last_block_dev = last_block_dev;
|
int c_last_block_dev = last_block_dev;
|
||||||
for (int i = 0; i < c_last_block_dev; ++i) {
|
for (int i = 0; i < c_last_block_dev; ++i) {
|
||||||
if (block_devices[i].flags.scanned || !block_devices[i].flags.present) continue;
|
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) {
|
for (size_t j = 0; j < NUM_DRIVERS; ++j) {
|
||||||
// only partitioning drivers are automatically assigned
|
// only partitioning drivers are automatically assigned
|
||||||
if (!DRIVER(i)->flags.partitioning) {
|
if (!DRIVER(i)->flags.partitioning) {
|
||||||
@@ -109,15 +104,13 @@ void block_dev_scan() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// let the driver test the disk
|
// 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) {
|
if (driver_result == BLOCK_DEV_DRIVER_CHECK_OK) {
|
||||||
block_devices[i].driver = DRIVER(j);
|
block_devices[i].driver = DRIVER(j);
|
||||||
block_devices[i].flags.driver_installed = 1;
|
block_devices[i].flags.driver_installed = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_block_dev_scan_free:
|
|
||||||
free(lba0);
|
|
||||||
block_devices[i].flags.scanned = 1;
|
block_devices[i].flags.scanned = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,7 +125,7 @@ void att_noreturn block_dev_task(void *data) {
|
|||||||
void block_dev_start_task() {
|
void block_dev_start_task() {
|
||||||
block_semaphore = semaphore_create(1);
|
block_semaphore = semaphore_create(1);
|
||||||
blockdev_task_running = true;
|
blockdev_task_running = true;
|
||||||
task_spawn(block_dev_task, NULL);
|
task_spawn(block_dev_task, NULL, "blockdev");
|
||||||
}
|
}
|
||||||
|
|
||||||
void block_dev_print_info() {
|
void block_dev_print_info() {
|
||||||
@@ -142,4 +135,10 @@ void block_dev_print_info() {
|
|||||||
block_devices[i].identifier,
|
block_devices[i].identifier,
|
||||||
block_devices[i].flags.driver_installed ? block_devices[i].driver->name : "n/a");
|
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
437
kernel/vfs/lfs/ext2.c
Normal 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,
|
||||||
|
};
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <myke/fs/blockdev.h>
|
#include <myke/vfs/blockdev.h>
|
||||||
|
|
||||||
#define FAT_TYPE_12 1
|
#define FAT_TYPE_12 1
|
||||||
#define FAT_TYPE_16 2
|
#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;
|
fat_bpb bpb;
|
||||||
memcpy((uint8_t *) &bpb, first_sector, sizeof(fat_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) {
|
if (bpb.bpb.sectors_per_fat == 0 || bpb.bpb.sectors_per_cluster == 0) {
|
||||||
printf("Definitely not FAT\n");
|
printf("Definitely not FAT\n");
|
||||||
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
|
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <myke/fs/blockdev.h>
|
#include <myke/vfs/blockdev.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char filename[100];
|
char filename[100];
|
||||||
@@ -75,15 +75,20 @@ ustar_sector *ustar_next(ustar_sector *current) {
|
|||||||
return ustar_sector_valid(next) ? next : NULL;
|
return ustar_sector_valid(next) ? next : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ustar_check_device(const block_device_t *device, uint8_t *first_sector) {
|
uint8_t ustar_check_device(const block_device_t *device) {
|
||||||
ustar_sector *sector = (ustar_sector *) first_sector;
|
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)) {
|
if (!ustar_sector_valid(sector)) {
|
||||||
|
free(sector);
|
||||||
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
|
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
ustar_fs *fs = malloc(sizeof(ustar_fs));
|
ustar_fs *fs = malloc(sizeof(ustar_fs));
|
||||||
fs->first_inode = malloc(sizeof(ustar_inode));
|
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->first_inode->lba = 0;
|
||||||
fs->device = device;
|
fs->device = device;
|
||||||
|
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <myke/drivers/pci/ide.h>
|
#include <myke/drivers/pci/ide.h>
|
||||||
#include <myke/fs/blockdev.h>
|
#include <myke/vfs/blockdev.h>
|
||||||
#include <myke/fs/mbr.h>
|
#include <myke/vfs/part/mbr.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t bootable;
|
uint8_t bootable;
|
||||||
@@ -33,12 +33,11 @@ typedef struct {
|
|||||||
} att_packed mbr_table;
|
} att_packed mbr_table;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const block_device_t *device;
|
block_device_t *device;
|
||||||
uint32_t start_lba;
|
uint32_t start_lba;
|
||||||
} mbr_block_driver_info;
|
} mbr_block_driver_info;
|
||||||
|
|
||||||
uint8_t
|
uint8_t mbr_block_dev_access(block_device_t *device, uint8_t direction, uint32_t lba, uint8_t sectors, void *target) {
|
||||||
mbr_block_dev_access(const block_device_t *device, uint8_t direction, uint32_t lba, uint8_t sectors, void *target) {
|
|
||||||
if (!device->flags.present || lba > device->num_lba) {
|
if (!device->flags.present || lba > device->num_lba) {
|
||||||
return BLOCK_DEV_ACCESS_ERR;
|
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);
|
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;
|
mbr_table table;
|
||||||
memcpy((uint8_t *) &table, first_sector + (device->block_size - sizeof(mbr_table)), sizeof(mbr_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
|
if (table.signature[0] != 0x55 && table.signature[1] != 0xAA) { // AA 55 but in little endian
|
||||||
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
|
return BLOCK_DEV_DRIVER_CHECK_NO_MATCH;
|
||||||
}
|
}
|
||||||
14
kernel/vfs/tmpfs.c
Normal file
14
kernel/vfs/tmpfs.c
Normal 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
186
kernel/vfs/vfs.c
Normal 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 = ¤t_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 = ¤t_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
1
lai
Submodule
Submodule lai added at 432546ee09
12
linker.ld
12
linker.ld
@@ -30,14 +30,26 @@ SECTIONS
|
|||||||
.data BLOCK(4K) : ALIGN(4K)
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
*(.data)
|
*(.data)
|
||||||
|
|
||||||
. = ALIGN(16);
|
. = ALIGN(16);
|
||||||
__start_pci_driver = .;
|
__start_pci_driver = .;
|
||||||
*(SORT(.pci_driver.*))
|
*(SORT(.pci_driver.*))
|
||||||
__stop_pci_driver = .;
|
__stop_pci_driver = .;
|
||||||
|
|
||||||
. = ALIGN(16);
|
. = ALIGN(16);
|
||||||
__start_block_dev_driver = .;
|
__start_block_dev_driver = .;
|
||||||
*(SORT(.block_dev_driver.*))
|
*(SORT(.block_dev_driver.*))
|
||||||
__stop_block_dev_driver = .;
|
__stop_block_dev_driver = .;
|
||||||
|
|
||||||
|
. = 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 */
|
/* Read-write data (uninitialized) and stack */
|
||||||
|
|||||||
3
rootfs/.gitignore
vendored
Normal file
3
rootfs/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
mnt/*
|
||||||
|
!mnt
|
||||||
|
rootfs.img
|
||||||
52
rootfs/mkrootfs.sh
Executable file
52
rootfs/mkrootfs.sh
Executable 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
39
rootfs/mount_rootfs.sh
Executable 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
15
rootfs/umount_rootfsh.sh
Executable 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}"
|
||||||
Reference in New Issue
Block a user