Compare commits
No commits in common. "c9bd659f5c9f1ceee1742d8bdd0a3421c052f002" and "d4e6dd4da8456e42ae7028364bc0dafb8ee55ca3" have entirely different histories.
c9bd659f5c
...
d4e6dd4da8
188
arch/uefi_x64/boot.s → arch/i386/boot.s
Normal file → Executable file
188
arch/uefi_x64/boot.s → arch/i386/boot.s
Normal file → Executable file
|
@ -1,94 +1,94 @@
|
|||
[BITS 32] ;... somehow.
|
||||
|
||||
[GLOBAL start]
|
||||
start:
|
||||
mov esp, _sys_stack ; Stack pointer!
|
||||
jmp stublet ; This has a purpse. I don't know what it is, but there is one.
|
||||
|
||||
ALIGN 4 ; 4KB alignment, required by GRUB.
|
||||
mboot: ; This is all magic, and all of it required for GRUB to see our stuff.
|
||||
MULTIBOOT_ALIGN equ 1<<0
|
||||
MULTIBOOT_MEM equ 1<<1
|
||||
MULTIBOOT_AOUT equ 1<<16
|
||||
MULTIBOOT_MAGIC equ 0x1BADB002
|
||||
MULTIBOOT_FLAGS equ MULTIBOOT_ALIGN | MULTIBOOT_MEM | MULTIBOOT_AOUT
|
||||
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS)
|
||||
EXTERN code, bss, end
|
||||
|
||||
dd MULTIBOOT_MAGIC
|
||||
dd MULTIBOOT_FLAGS
|
||||
dd MULTIBOOT_CHECKSUM
|
||||
|
||||
dd mboot
|
||||
dd code
|
||||
dd bss
|
||||
dd end
|
||||
dd start
|
||||
|
||||
stublet: ; Where the kernel stuff goes.
|
||||
|
||||
;=====================================
|
||||
;===Priority: 32 bit Protected Mode===
|
||||
;=====================================
|
||||
|
||||
cli ; Interrupts be gone!
|
||||
|
||||
xor cx, cx ; CX - GP, useful here.
|
||||
kbempty:
|
||||
in al, 64h ; Read keyboard status
|
||||
test al, 02h ; Check if the buffer is full
|
||||
loopnz kbempty ; Wait until it is
|
||||
mov al, 0d1h ; Prepare a message
|
||||
out 64h, al ; And then send it to the keyboard (controller)
|
||||
kbempty2:
|
||||
in al, 64h ; Read the status again
|
||||
test al, 02h ; Check if it's processed our message
|
||||
loopnz kbempty2 ; And wait until it has
|
||||
mov al, 0dfh ; Prepare a different message, telling it to enable A20
|
||||
out 60h, al ; Send the message
|
||||
mov cx, 14h ; Restore the value of CX
|
||||
wait_kb: ; Insinuate a 25uS delay to allow the processor to catch up
|
||||
out 0edh, ax
|
||||
loop wait_kb
|
||||
|
||||
mov eax, cr0 ; Read the control register
|
||||
or al, 1 ; Set bit 1: protected mode
|
||||
mov cr0, eax ; Set the control register back
|
||||
jmp $+2 ; Clear the queue
|
||||
nop ; (jump straight to kernel)
|
||||
nop
|
||||
|
||||
;==================================
|
||||
;===32-bit Protected Mode active===
|
||||
;==================================
|
||||
; Call the kernel
|
||||
|
||||
EXTERN kernel_main
|
||||
call kernel_main
|
||||
jmp $
|
||||
|
||||
[GLOBAL load_gdt]
|
||||
[EXTERN gp]
|
||||
load_gdt:
|
||||
lgdt [gp] ; Load the new GDT pointer
|
||||
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
jmp 0x08:flush
|
||||
flush:
|
||||
ret
|
||||
|
||||
[GLOBAL idt_load]
|
||||
[EXTERN idtp]
|
||||
idt_load:
|
||||
lidt [idtp]
|
||||
ret
|
||||
|
||||
|
||||
SECTION .bss
|
||||
resb 8192
|
||||
_sys_stack:
|
||||
[BITS 32] ;... somehow.
|
||||
|
||||
[GLOBAL start]
|
||||
start:
|
||||
mov esp, _sys_stack ; Stack pointer!
|
||||
jmp stublet ; This has a purpse. I don't know what it is, but there is one.
|
||||
|
||||
ALIGN 4 ; 4KB alignment, required by GRUB.
|
||||
mboot: ; This is all magic, and all of it required for GRUB to see our stuff.
|
||||
MULTIBOOT_ALIGN equ 1<<0
|
||||
MULTIBOOT_MEM equ 1<<1
|
||||
MULTIBOOT_AOUT equ 1<<16
|
||||
MULTIBOOT_MAGIC equ 0x1BADB002
|
||||
MULTIBOOT_FLAGS equ MULTIBOOT_ALIGN | MULTIBOOT_MEM | MULTIBOOT_AOUT
|
||||
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS)
|
||||
EXTERN code, bss, end
|
||||
|
||||
dd MULTIBOOT_MAGIC
|
||||
dd MULTIBOOT_FLAGS
|
||||
dd MULTIBOOT_CHECKSUM
|
||||
|
||||
dd mboot
|
||||
dd code
|
||||
dd bss
|
||||
dd end
|
||||
dd start
|
||||
|
||||
stublet: ; Where the kernel stuff goes.
|
||||
|
||||
;=====================================
|
||||
;===Priority: 32 bit Protected Mode===
|
||||
;=====================================
|
||||
|
||||
cli ; Interrupts be gone!
|
||||
|
||||
xor cx, cx ; CX - GP, useful here.
|
||||
kbempty:
|
||||
in al, 64h ; Read keyboard status
|
||||
test al, 02h ; Check if the buffer is full
|
||||
loopnz kbempty ; Wait until it is
|
||||
mov al, 0d1h ; Prepare a message
|
||||
out 64h, al ; And then send it to the keyboard (controller)
|
||||
kbempty2:
|
||||
in al, 64h ; Read the status again
|
||||
test al, 02h ; Check if it's processed our message
|
||||
loopnz kbempty2 ; And wait until it has
|
||||
mov al, 0dfh ; Prepare a different message, telling it to enable A20
|
||||
out 60h, al ; Send the message
|
||||
mov cx, 14h ; Restore the value of CX
|
||||
wait_kb: ; Insinuate a 25uS delay to allow the processor to catch up
|
||||
out 0edh, ax
|
||||
loop wait_kb
|
||||
|
||||
mov eax, cr0 ; Read the control register
|
||||
or al, 1 ; Set bit 1: protected mode
|
||||
mov cr0, eax ; Set the control register back
|
||||
jmp $+2 ; Clear the queue
|
||||
nop ; (jump straight to kernel)
|
||||
nop
|
||||
|
||||
;==================================
|
||||
;===32-bit Protected Mode active===
|
||||
;==================================
|
||||
; Call the kernel
|
||||
|
||||
EXTERN kernel_main
|
||||
call kernel_main
|
||||
jmp $
|
||||
|
||||
[GLOBAL load_gdt]
|
||||
[EXTERN gp]
|
||||
load_gdt:
|
||||
lgdt [gp] ; Load the new GDT pointer
|
||||
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
jmp 0x08:flush
|
||||
flush:
|
||||
ret
|
||||
|
||||
[GLOBAL idt_load]
|
||||
[EXTERN idtp]
|
||||
idt_load:
|
||||
lidt [idtp]
|
||||
ret
|
||||
|
||||
|
||||
SECTION .bss
|
||||
resb 8192
|
||||
_sys_stack:
|
50
arch/uefi_x64/linker.ld → arch/i386/linker.ld
Normal file → Executable file
50
arch/uefi_x64/linker.ld → arch/i386/linker.ld
Normal file → Executable file
|
@ -1,25 +1,25 @@
|
|||
OUTPUT_FORMAT("elf32-i386")
|
||||
ENTRY(start)
|
||||
phys = 0x00100000;
|
||||
SECTIONS
|
||||
{
|
||||
.text phys : AT(phys) {
|
||||
code = .;
|
||||
*(.text)
|
||||
*(.rodata)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.data : AT(phys + (data - code))
|
||||
{
|
||||
data = .;
|
||||
*(.data)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.bss : AT(phys + (bss - code))
|
||||
{
|
||||
bss = .;
|
||||
*(.bss)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
end = .;
|
||||
}
|
||||
OUTPUT_FORMAT("elf32-i386")
|
||||
ENTRY(start)
|
||||
phys = 0x00100000;
|
||||
SECTIONS
|
||||
{
|
||||
.text phys : AT(phys) {
|
||||
code = .;
|
||||
*(.text)
|
||||
*(.rodata)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.data : AT(phys + (data - code))
|
||||
{
|
||||
data = .;
|
||||
*(.data)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.bss : AT(phys + (bss - code))
|
||||
{
|
||||
bss = .;
|
||||
*(.bss)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
end = .;
|
||||
}
|
18
arch/uefi_x64/make.config → arch/i386/make.config
Normal file → Executable file
18
arch/uefi_x64/make.config → arch/i386/make.config
Normal file → Executable file
|
@ -1,9 +1,9 @@
|
|||
KERNEL_ARCH_CFLAGS=
|
||||
KERNEL_ARCH_CPPFLAGS=
|
||||
KERNEL_ARCH_LDFLAGS=
|
||||
KERNEL_ARCH_LIBS=
|
||||
|
||||
KERNEL_ARCH_OBJS= \
|
||||
$(ARCHDIR)/boot.o \
|
||||
$(ARCHDIR)/sys_clock.o \
|
||||
$(ARCHDIR)/tty.o
|
||||
KERNEL_ARCH_CFLAGS=
|
||||
KERNEL_ARCH_CPPFLAGS=
|
||||
KERNEL_ARCH_LDFLAGS=
|
||||
KERNEL_ARCH_LIBS=
|
||||
|
||||
KERNEL_ARCH_OBJS= \
|
||||
$(ARCHDIR)/boot.o \
|
||||
$(ARCHDIR)/sys_clock.o \
|
||||
$(ARCHDIR)/tty.o
|
68
arch/uefi_x64/sys_clock.c → arch/i386/sys_clock.c
Normal file → Executable file
68
arch/uefi_x64/sys_clock.c → arch/i386/sys_clock.c
Normal file → Executable file
|
@ -1,35 +1,35 @@
|
|||
/************************
|
||||
*** Team Kitty, 2019 ***
|
||||
*** Sync ***
|
||||
***********************/
|
||||
|
||||
/* This file provides an interface to
|
||||
* the hardware timer / RTC. Not much
|
||||
* more to be said about it. */
|
||||
|
||||
#include <kernel/utils.h>
|
||||
#include <kernel.h>
|
||||
#include <kernel/serial.h>
|
||||
#include <kernel/descriptor_tables.h>
|
||||
|
||||
size_t timer_ticks = 0;
|
||||
size_t flag = 0;
|
||||
void timer_handler(struct int_frame* r) {
|
||||
gdb_end();
|
||||
timer_ticks++;
|
||||
|
||||
if(timer_ticks % 18 == 0) {
|
||||
if(++flag % 2 == 0) {
|
||||
serial_print(0x3F8, "Tick.");
|
||||
} else {
|
||||
serial_print(0x3F8, "Tock.");
|
||||
}
|
||||
}
|
||||
|
||||
if(timer_ticks > 18)
|
||||
timer_ticks = 0;
|
||||
}
|
||||
|
||||
void timer_install() {
|
||||
irq_install_handler(0, &timer_handler);
|
||||
/************************
|
||||
*** Team Kitty, 2019 ***
|
||||
*** Sync ***
|
||||
***********************/
|
||||
|
||||
/* This file provides an interface to
|
||||
* the hardware timer / RTC. Not much
|
||||
* more to be said about it. */
|
||||
|
||||
#include <kernel/utils.h>
|
||||
#include <kernel.h>
|
||||
#include <kernel/serial.h>
|
||||
#include <kernel/descriptor_tables.h>
|
||||
|
||||
size_t timer_ticks = 0;
|
||||
size_t flag = 0;
|
||||
void timer_handler(struct int_frame* r) {
|
||||
gdb_end();
|
||||
timer_ticks++;
|
||||
|
||||
if(timer_ticks % 18 == 0) {
|
||||
if(++flag % 2 == 0) {
|
||||
serial_print(0x3F8, "Tick.");
|
||||
} else {
|
||||
serial_print(0x3F8, "Tock.");
|
||||
}
|
||||
}
|
||||
|
||||
if(timer_ticks > 18)
|
||||
timer_ticks = 0;
|
||||
}
|
||||
|
||||
void timer_install() {
|
||||
irq_install_handler(0, &timer_handler);
|
||||
}
|
907
include/kernel.h
907
include/kernel.h
|
@ -1,911 +1,12 @@
|
|||
/************************
|
||||
*** Team Kitty, 2019 ***
|
||||
*** Sync ***
|
||||
*** ProjectRED ***
|
||||
***********************/
|
||||
|
||||
/* ==================== Kernel Header ==================== */
|
||||
/* This file contains most of the shared code for the kernel and
|
||||
* the classes it interacts with.
|
||||
*
|
||||
* Most of this file is constants and struct definitions. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#define SYNC_MAJOR_VERSION 1
|
||||
#define SYNC_MINOR_VERSION 0
|
||||
|
||||
|
||||
/* ==================== Standard Headers ==================== */
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <float.h>
|
||||
#include <stddef.h>
|
||||
#include <kernel/tty.h>
|
||||
|
||||
#include <efibind.h>
|
||||
#include <efitypes.h>
|
||||
#include <efierr.h>
|
||||
|
||||
/* ==================== Custom Headers ==================== */
|
||||
//#include "AVX.h"
|
||||
|
||||
/* ==================== EFI structs and constants ==================== */
|
||||
|
||||
/* ========= Graphics ========== */
|
||||
typedef struct {
|
||||
uint32_t RedMask;
|
||||
uint32_t GreenMask;
|
||||
uint32_t BlueMask;
|
||||
uint32_t ReservedMask;
|
||||
} EFI_PIXEL_BITMASK;
|
||||
|
||||
typedef enum {
|
||||
PixelRedGreenBlueReserved8BitPerColor,
|
||||
PixelBlueRedGreenReserved8BitPerColor,
|
||||
PixelBitMask,
|
||||
PixelBitOnly,
|
||||
PixelFormatMax
|
||||
} EFI_GRAPHICS_PIXEL_FORMAT;
|
||||
|
||||
typedef struct {
|
||||
uint32_t Version;
|
||||
uint32_t HorizontalResolution;
|
||||
uint32_t VerticalResolution;
|
||||
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
|
||||
EFI_PIXEL_BITMASK PixelInformation;
|
||||
uint32_t PixelsPerScanline;
|
||||
} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
|
||||
|
||||
typedef struct {
|
||||
uint32_t MaxMode;
|
||||
uint32_t Mode;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* Info;
|
||||
size_t SizeOfInfo;
|
||||
EFI_PHYSICAL_ADDRESS FrameBufferBase;
|
||||
size_t FrameBufferSize;
|
||||
} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
|
||||
|
||||
/* ========== Time ========== */
|
||||
|
||||
typedef struct {
|
||||
uint32_t Resolution;
|
||||
uint32_t Accuracy;
|
||||
BOOLEAN SetsToZero;
|
||||
} EFI_TIME_CAPABILITIES;
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_GET_TIME) (
|
||||
OUT EFI_TIME* Time,
|
||||
OUT EFI_TIME_CAPABILITIES* Capabilities OPTIONAL
|
||||
);
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_SET_TIME) (
|
||||
IN EFI_TIME* Time
|
||||
);
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_GET_WAKEUP_TIME) (
|
||||
OUT BOOLEAN* Enabled,
|
||||
OUT BOOLEAN* Pending,
|
||||
OUT EFI_TIME* Time
|
||||
);
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_SET_WAKEUP_TIME) (
|
||||
IN BOOLEAN Enable,
|
||||
IN EFI_TIME* Time OPTIONAL
|
||||
);
|
||||
|
||||
/* ========== Variables ========== */
|
||||
|
||||
#define EFI_GLOBAL_VARIABLE \
|
||||
{ 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C} }
|
||||
|
||||
|
||||
#define EFI_VARIABLE_NON_VOLATILE 0x00000001
|
||||
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
|
||||
#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
|
||||
#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008
|
||||
#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
|
||||
#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020
|
||||
#define EFI_VARIABLE_APPEND_WRITE 0x00000040
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_GET_VARIABLE) (
|
||||
IN CHAR16* VariableName,
|
||||
IN EFI_GUID* VendorGuid,
|
||||
OUT uint32_t* Attributes OPTIONAL,
|
||||
IN OUT size_t* DataSize,
|
||||
OUT void* Data
|
||||
);
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_GET_NEXT_VARIABLE_NAME) (
|
||||
IN OUT size_t* VariableNameSize,
|
||||
IN OUT CHAR16* VariableName,
|
||||
IN OUT EFI_GUID* VendorGuid
|
||||
);
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_SET_VARIABLE) (
|
||||
IN CHAR16* VariableName,
|
||||
IN EFI_GUID* VendorGuid,
|
||||
IN uint32_t Attributes,
|
||||
IN size_t DataSize,
|
||||
IN void* Data
|
||||
);
|
||||
|
||||
/* ========== Memory ========== */
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_SET_VIRTUAL_ADDRESS_MAP) (
|
||||
IN size_t MemoryMapSize,
|
||||
IN size_t DescriptorSize,
|
||||
IN uint32_t DescriptorVersion,
|
||||
IN EFI_MEMORY_DESCRIPTOR* VirtualMap
|
||||
);
|
||||
|
||||
|
||||
#define EFI_OPTIONAL_PTR 0x00000001
|
||||
#define EFI_INTERNAL_FNC 0x00000002
|
||||
#define EFI_INTERNAL_PTR 0x00000004
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_CONVERT_POINTER) (
|
||||
IN size_t DebugDeposition,
|
||||
IN OUT void* *Address
|
||||
);
|
||||
|
||||
/* ========== Reset ========== */
|
||||
|
||||
typedef enum {
|
||||
EfiResetCold,
|
||||
EfiResetWarm,
|
||||
EfiResetShutdown
|
||||
} EFI_RESET_TYPE;
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_RESET_SYSTEM) (
|
||||
IN EFI_RESET_TYPE ResetType,
|
||||
IN EFI_STATUS ResetStatus,
|
||||
IN size_t DataSize,
|
||||
IN CHAR16* ResetData OPTIONAL
|
||||
);
|
||||
|
||||
|
||||
/* ========== Other ========== */
|
||||
|
||||
typedef EFI_STATUS(EFIAPI* EFI_GET_NEXT_HIGH_MONO_COUNT) (
|
||||
OUT uint32_t* HighCount
|
||||
);
|
||||
|
||||
|
||||
/* ===== Capsule ===== */
|
||||
|
||||
typedef struct {
|
||||
EFI_GUID CapsuleGuid;
|
||||
uint32_t HeaderSize;
|
||||
uint32_t Flags;
|
||||
uint32_t CapsuleImageSize;
|
||||
} EFI_CAPSULE_HEADER;
|
||||
|
||||
#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000
|
||||
#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000
|
||||
#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_UPDATE_CAPSULE) (
|
||||
IN EFI_CAPSULE_HEADER* *CapsuleHeaderArray,
|
||||
IN size_t CapsuleCount,
|
||||
IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL
|
||||
);
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_QUERY_CAPSULE_CAPABILITIES) (
|
||||
IN EFI_CAPSULE_HEADER* *CapsuleHeaderArray,
|
||||
IN size_t CapsuleCount,
|
||||
OUT size_t* MaximumCapsuleSize,
|
||||
OUT EFI_RESET_TYPE* ResetType
|
||||
);
|
||||
|
||||
typedef EFI_STATUS (EFIAPI* EFI_QUERY_VARIABLE_INFO) (
|
||||
IN uint32_t Attributes,
|
||||
OUT size_t* MaximumVariableStorage,
|
||||
OUT size_t* RemainingVariableStorageSize,
|
||||
OUT size_t* MaximumVariableSize
|
||||
);
|
||||
|
||||
|
||||
/* ==================== EFI Runtime Services ==================== */
|
||||
|
||||
typedef struct {
|
||||
EFI_TABLE_HEADER Header;
|
||||
|
||||
/* Time */
|
||||
EFI_GET_TIME GetTime;
|
||||
EFI_SET_TIME SetTime;
|
||||
EFI_GET_WAKEUP_TIME GetWakeupTime;
|
||||
EFI_SET_WAKEUP_TIME SetWakeupTime;
|
||||
|
||||
/* Virtual Memory */
|
||||
EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap;
|
||||
EFI_CONVERT_POINTER ConvertPointer;
|
||||
|
||||
/* Variable Services */
|
||||
EFI_GET_VARIABLE GetVariable;
|
||||
EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName;
|
||||
EFI_SET_VARIABLE SetVariable;
|
||||
|
||||
/* Other */
|
||||
EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonoCount;
|
||||
EFI_RESET_SYSTEM ResetSystem;
|
||||
|
||||
/* Capsule Services */
|
||||
EFI_UPDATE_CAPSULE UpdateCapsule;
|
||||
EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities;
|
||||
EFI_QUERY_VARIABLE_INFO QueryVariableInfo;
|
||||
|
||||
} EFI_RUNTIME_SERVICES;
|
||||
|
||||
|
||||
/* ==================== EFI File Info ==================== */
|
||||
|
||||
typedef struct {
|
||||
size_t Size;
|
||||
size_t FileSize;
|
||||
size_t PhysicalSize;
|
||||
EFI_TIME CreateTime;
|
||||
EFI_TIME LastAccessTime;
|
||||
EFI_TIME ModificationTime;
|
||||
size_t Attribute;
|
||||
CHAR16 FileName[1];
|
||||
} EFI_FILE_INFO;
|
||||
|
||||
/* ==================== EFI System Configuration Tables ==================== */
|
||||
|
||||
|
||||
#define MPS_TABLE_GUID \
|
||||
{ 0xeb9d2d2f, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
|
||||
|
||||
#define ACPI_10_TABLE_GUID \
|
||||
{ 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
|
||||
|
||||
#define ACPI_20_TABLE_GUID \
|
||||
{ 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} }
|
||||
|
||||
#define SMBIOS_TABLE_GUID \
|
||||
{ 0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
|
||||
|
||||
#define SMBIOS3_TABLE_GUID \
|
||||
{ 0xf2fd1544, 0x9794, 0x4a2c, {0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94} }
|
||||
|
||||
#define SAL_SYSTEM_TABLE_GUID \
|
||||
{ 0xeb9d2d32, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
|
||||
|
||||
static const EFI_GUID MpsTableGuid = MPS_TABLE_GUID;
|
||||
static const EFI_GUID Acpi10TableGuid = ACPI_10_TABLE_GUID;
|
||||
static const EFI_GUID Acpi20TableGuid = ACPI_20_TABLE_GUID;
|
||||
static const EFI_GUID SmBiosTableGuid = SMBIOS_TABLE_GUID;
|
||||
static const EFI_GUID SmBios3TableGuid = SMBIOS3_TABLE_GUID;
|
||||
static const EFI_GUID SalSystemTableGuid = SAL_SYSTEM_TABLE_GUID;
|
||||
|
||||
typedef struct _EFI_CONFIGURATION_TABLE {
|
||||
EFI_GUID VendorGuid;
|
||||
void* VendorTable;
|
||||
} EFI_CONFIGURATION_TABLE;
|
||||
|
||||
/* ============================================================= */
|
||||
/* = Syncboot Structures = */
|
||||
/* ============================================================= */
|
||||
|
||||
typedef struct {
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE* GPUs;
|
||||
size_t FBCount;
|
||||
} GPU_INFO;
|
||||
|
||||
typedef struct {
|
||||
uint32_t UEFI_Version;
|
||||
uint32_t SYNCBOOT_Major;
|
||||
uint32_t SYNCBOOT_Minor;
|
||||
|
||||
uint32_t MemoryMapDescriptorVersion;
|
||||
size_t MemoryMapDescriptorSize;
|
||||
EFI_MEMORY_DESCRIPTOR* MemoryMap;
|
||||
size_t MemoryMap_Size;
|
||||
EFI_PHYSICAL_ADDRESS KernelBase;
|
||||
size_t KernelPages;
|
||||
|
||||
CHAR16* ESPRootPath;
|
||||
size_t ESPRootPathSize;
|
||||
CHAR16* KernelPath;
|
||||
size_t KernelPathSize;
|
||||
CHAR16* KernelOptions;
|
||||
size_t KernelOptionsSize;
|
||||
|
||||
EFI_RUNTIME_SERVICES* RTServices;
|
||||
GPU_INFO* GPU_Info;
|
||||
EFI_FILE_INFO* KernelFileMetadata;
|
||||
EFI_CONFIGURATION_TABLE* ConfigurationTables;
|
||||
size_t NumConfigurationTables;
|
||||
} FILELOADER_PARAMS;
|
||||
|
||||
|
||||
/* ============================================================= */
|
||||
/* = Sync Structures = */
|
||||
/* ============================================================= */
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t MemoryMapDescriptorVersion;
|
||||
size_t MemoryMapDescriptorSize;
|
||||
size_t MemoryMapSize;
|
||||
EFI_MEMORY_DESCRIPTOR* MemoryMap;
|
||||
uint32_t Pad;
|
||||
} MEMORY_INFO;
|
||||
|
||||
typedef struct {
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE defaultGPU;
|
||||
uint32_t charHeight;
|
||||
uint32_t charWidth; // Bit width
|
||||
uint32_t charFGColor; // ForeGround Color
|
||||
uint32_t charHLColor; // HighLight Color
|
||||
uint32_t charBGColor; // BackGround Color
|
||||
uint32_t screenMinX; // Far left side of the screen
|
||||
uint32_t screenMinY; // Top of the screen
|
||||
uint32_t ScreenScale;
|
||||
uint32_t cursorPos;
|
||||
uint32_t scrollMode; // Move screen up, or wraparound
|
||||
} PRINT_INFO;
|
||||
|
||||
/* ==================== GDT ==================== */
|
||||
|
||||
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t LowLimit;
|
||||
uint16_t LowBase;
|
||||
uint8_t MiddleBase;
|
||||
uint8_t Access;
|
||||
uint8_t Granularity;
|
||||
uint8_t HighBase;
|
||||
} GDT_ENTRY;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t Limit;
|
||||
size_t BaseAddress;
|
||||
} DESCRIPTOR_TABLE_POINTER;
|
||||
|
||||
GDT_ENTRY gdt[3]; //3-entry gdt
|
||||
DESCRIPTOR_TABLE_POINTER gtdp;
|
||||
|
||||
|
||||
/* ==================== IDT ==================== */
|
||||
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t LowBase;
|
||||
uint16_t Segment;
|
||||
uint8_t IST;
|
||||
uint8_t SegmentType;
|
||||
uint16_t MiddleBase;
|
||||
uint32_t HighBase;
|
||||
uint32_t Reserved;
|
||||
} IDT_GATE;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t LowBase;
|
||||
uint16_t Selector;
|
||||
uint8_t IST;
|
||||
uint8_t Flags;
|
||||
uint16_t HighBase;
|
||||
} IDT_ENTRY;
|
||||
|
||||
IDT_ENTRY idt[256];
|
||||
DESCRIPTOR_TABLE_POINTER idtp; // IDT Pointer
|
||||
|
||||
/* ==================== TSS ==================== */
|
||||
|
||||
/* Intel Architecture Manual Vol. 3A, Fig. 7-4 (Format of TSS and LDT Descriptors in 64-bit Mode)
|
||||
*
|
||||
* Segment Limit is a 20-bit value - the lower 16 bits are stored at SegmentLimitLow and the higher 4 bits at SegmentLimitHigh;
|
||||
* Base Address is a 64-bit value - The lower 24 bits are stored at Low and Middle1, the upper 46 bits at Middle2 and High.
|
||||
* SegmentType stores the following:
|
||||
*
|
||||
* =========================
|
||||
* | 0 - 3 | 4 | 5 6 | 7 |
|
||||
* | SEGType | S | DPL | P |
|
||||
* =========================
|
||||
*
|
||||
* SegmentLimitHigh stores the following:
|
||||
*
|
||||
* ==========================================
|
||||
* | 0 - 3 | 4 | 5 | 6 | 7 |
|
||||
* | SegmentLimit | Avail | L | D/B | Gran |
|
||||
* ==========================================
|
||||
*
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t SegmentLimitLow;
|
||||
uint16_t BaseLow;
|
||||
uint8_t BaseMiddle1;
|
||||
uint8_t SegmentType;
|
||||
uint8_t SegmentLimitHigh;
|
||||
uint8_t BaseMiddle2;
|
||||
uint32_t BaseHigh;
|
||||
uint32_t Reserved;
|
||||
} TSS_ENTRY;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t SegmentSelector;
|
||||
uint16_t SegmentType;
|
||||
uint16_t SegmentLow;
|
||||
uint32_t SegmentHigh;
|
||||
uint32_t Reserved;
|
||||
} CALL_GATE_ENTRY;
|
||||
|
||||
/* Intel Architecture Manual Vol. 3A, Fig. 7-11 (64-Bit TSS Format)
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t Reserved0;
|
||||
size_t RSP0;
|
||||
size_t RSP1;
|
||||
size_t RSP2;
|
||||
|
||||
size_t Reserved12;
|
||||
|
||||
size_t IST1;
|
||||
size_t IST2;
|
||||
size_t IST3;
|
||||
size_t IST4;
|
||||
size_t IST5;
|
||||
size_t IST6;
|
||||
size_t IST7;
|
||||
|
||||
size_t Reserved34;
|
||||
|
||||
uint16_t Reserved5;
|
||||
uint16_t IOMap;
|
||||
|
||||
} TSS_64;
|
||||
|
||||
|
||||
/* ==================== ACPI ==================== */
|
||||
|
||||
/*
|
||||
* ACPI Specification 6.2A, section 5.2.5 (Root System Description Pointer (RSDP))
|
||||
*/
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
char Signature[8]; // "RSD PTR "
|
||||
uint8_t Checksum;
|
||||
char OEMID[6];
|
||||
uint8_t Revision;
|
||||
uint32_t RSDT; // 32 bit
|
||||
} RSDP_10;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
RSDP_10 RSDP_10_Section;
|
||||
uint32_t Length;
|
||||
size_t XSDT; // = 64 bit RSDT
|
||||
uint8_t ChecksumExtended;
|
||||
uint8_t Reserved[3];
|
||||
} RSDP_20;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
char Signature[4];
|
||||
uint32_t Length;
|
||||
uint8_t Revision;
|
||||
uint8_t Checksum;
|
||||
char OEMID[6];
|
||||
char OEMTableID[8];
|
||||
uint32_t OEMRevision;
|
||||
uint32_t CreatorID;
|
||||
uint32_t CreatorRevision;
|
||||
} SDTHeader; // System Descriptor Table
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
SDTHeader SDTHeader;
|
||||
size_t Entry[1];
|
||||
} XSDT;
|
||||
|
||||
|
||||
/* ==================== Global Variables ==================== */
|
||||
|
||||
MEMORY_INFO Memory_Info = {0};
|
||||
PRINT_INFO Print_Info = {0};
|
||||
|
||||
uint8_t Image[96] = {0};
|
||||
char BrandStr[48] = {0};
|
||||
char ManufacturerStr[13] = {0};
|
||||
|
||||
/* ==================== Interrupts ==================== */
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
size_t rip;
|
||||
size_t cs;
|
||||
size_t rflags;
|
||||
size_t rsp;
|
||||
size_t ss;
|
||||
} INTERRUPT_FRAME;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
size_t ErrorCode;
|
||||
size_t rip;
|
||||
size_t cs;
|
||||
size_t rflags;
|
||||
size_t rsp;
|
||||
size_t ss;
|
||||
} EXCEPTION_FRAME;
|
||||
|
||||
typedef struct __attribute__((aligned(64), packed)) {
|
||||
// Legacy FXSAVE header
|
||||
UINT16 fcw;
|
||||
UINT16 fsw;
|
||||
UINT8 ftw;
|
||||
UINT8 Reserved1;
|
||||
UINT16 fop;
|
||||
UINT64 fip;
|
||||
UINT64 fdp;
|
||||
UINT32 mxcsr;
|
||||
UINT32 mxcsr_mask;
|
||||
|
||||
// Legacy x87/MMX registers
|
||||
UINT64 st_mm_0[2];
|
||||
UINT64 st_mm_1[2];
|
||||
UINT64 st_mm_2[2];
|
||||
UINT64 st_mm_3[2];
|
||||
UINT64 st_mm_4[2];
|
||||
UINT64 st_mm_5[2];
|
||||
UINT64 st_mm_6[2];
|
||||
UINT64 st_mm_7[2];
|
||||
|
||||
// SSE registers
|
||||
UINT64 xmm0[2];
|
||||
UINT64 xmm1[2];
|
||||
UINT64 xmm2[2];
|
||||
UINT64 xmm3[2];
|
||||
UINT64 xmm4[2];
|
||||
UINT64 xmm5[2];
|
||||
UINT64 xmm6[2];
|
||||
UINT64 xmm7[2];
|
||||
UINT64 xmm8[2];
|
||||
UINT64 xmm9[2];
|
||||
UINT64 xmm10[2];
|
||||
UINT64 xmm11[2];
|
||||
UINT64 xmm12[2];
|
||||
UINT64 xmm13[2];
|
||||
UINT64 xmm14[2];
|
||||
UINT64 xmm15[2];
|
||||
UINT8 Reserved2[48];
|
||||
UINT8 pad[48];
|
||||
UINT64 xstate_bv;
|
||||
UINT64 xcomp_bv;
|
||||
UINT64 Reserved3[6];
|
||||
UINT8 extended_region[1];
|
||||
} XSAVE_AREA;
|
||||
|
||||
|
||||
static void* irq_routines[16] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
|
||||
static const char* exception_messages[] = {
|
||||
"Division by Zero",
|
||||
"Debug",
|
||||
"Non Maskable Interrupt",
|
||||
"Breakpoint",
|
||||
"Into Detected Overflow",
|
||||
"Out of Bounds",
|
||||
"Invalid Opcode",
|
||||
"No Coprocessor",
|
||||
"Double Fault",
|
||||
"Coprocessor Segment Overrun",
|
||||
"Bad TSS",
|
||||
"Segment Not Present",
|
||||
"Stack Fault",
|
||||
"General Protection Fault",
|
||||
"Page Fault",
|
||||
"Unknown Interrupt",
|
||||
"Coprocessor Fault",
|
||||
"Alignment Check",
|
||||
"Machine Check",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
|
||||
/* ============================================================= */
|
||||
/* = Sync Functions = */
|
||||
/* ============================================================= */
|
||||
|
||||
/* System Initialization */
|
||||
void PrepareSystem(FILELOADER_PARAMS* FLOP);
|
||||
|
||||
/* System Utilities */
|
||||
size_t ClockTick(void);
|
||||
void Halt(void);
|
||||
void PrepareAVX(void);
|
||||
void PrepareMaskableInterrupts(void);
|
||||
void PreparePowerManagement(void);
|
||||
|
||||
/* Hypervisor / Scheduler */
|
||||
uint8_t HypervisorCheck(void);
|
||||
uint8_t ReadPerformance(size_t* PerformanceDest);
|
||||
size_t ReadCPUFrequency(size_t* PerformanceDest, uint8_t AvgOrDirect);
|
||||
|
||||
/* Read/Write Port (eg. Serial) */
|
||||
uint32_t ReadPort(uint16_t Port, int Length);
|
||||
uint32_t WritePort(uint16_t Port, uint32_t Data, int Length);
|
||||
|
||||
/* ==================== Registers ==================== */
|
||||
size_t ReadModelSpecificRegister(size_t MSR);
|
||||
size_t WriteModelSpecificRegister(size_t MSR, size_t Data);
|
||||
|
||||
uint32_t ReadVexMXCSR(void);
|
||||
uint32_t WriteVexMXCSR(uint32_t Data);
|
||||
|
||||
uint32_t ReadMXCSR(void);
|
||||
uint32_t WriteMXCSR(uint32_t Data);
|
||||
|
||||
size_t ReadControlRegister(int CRX);
|
||||
size_t WriteControlRegister(int CRX, size_t Data);
|
||||
|
||||
size_t ReadExtendedControlRegister(size_t XCRX);
|
||||
size_t WriteExtendedControlRegister(size_t XCRX, size_t Data);
|
||||
|
||||
// XCS = Extended Code Segment
|
||||
size_t ReadXCS(void);
|
||||
|
||||
/* ==================== Descriptor Tables ==================== */
|
||||
DESCRIPTOR_TABLE_POINTER FetchGDT(void);
|
||||
void SetGDT(DESCRIPTOR_TABLE_POINTER GDTData);
|
||||
|
||||
DESCRIPTOR_TABLE_POINTER FetchIDT(void);
|
||||
void SetIDT(DESCRIPTOR_TABLE_POINTER IDTData);
|
||||
|
||||
DESCRIPTOR_TABLE_POINTER FetchLDT(void);
|
||||
void SetLDT(DESCRIPTOR_TABLE_POINTER LDTData);
|
||||
|
||||
DESCRIPTOR_TABLE_POINTER FetchTSR(void);
|
||||
void SetTSR(DESCRIPTOR_TABLE_POINTER TSRData);
|
||||
|
||||
void InstallGDT(void);
|
||||
void InstallIDT(void);
|
||||
void InstallPaging(void);
|
||||
|
||||
/* ==================== Branding ==================== */
|
||||
char* FetchBrandStr(uint32_t* Str);
|
||||
char* FetchManufacturer(char* ID);
|
||||
|
||||
void ScanCPUFeatures(size_t RAX, size_t RCX);
|
||||
|
||||
/* ==================== Interrupts ==================== */
|
||||
|
||||
void IRQ_Common(INTERRUPT_FRAME* Frame);
|
||||
void ISR_Common(INTERRUPT_FRAME* Frame);
|
||||
void ISR_Error_Common(EXCEPTION_FRAME* Frame);
|
||||
|
||||
void ISR0Handler(INTERRUPT_FRAME* Frame); // Divide-By-Zero
|
||||
void ISR1Handler(INTERRUPT_FRAME* Frame); // Debug
|
||||
void ISR2Handler(INTERRUPT_FRAME* Frame); // Non-Maskable Interrupt
|
||||
void ISR3Handler(INTERRUPT_FRAME* Frame); // Breakpoint
|
||||
void ISR4Handler(INTERRUPT_FRAME* Frame); // Overflow
|
||||
void ISR5Handler(INTERRUPT_FRAME* Frame); // Out-of-Bounds
|
||||
void ISR6Handler(INTERRUPT_FRAME* Frame); // Invalid Opcode
|
||||
void ISR7Handler(INTERRUPT_FRAME* Frame); // No Coprocessor
|
||||
void ISR8Handler(EXCEPTION_FRAME* Frame); // Double Fault
|
||||
void ISR9Handler(INTERRUPT_FRAME* Frame); // Coprocessor Overrun
|
||||
void ISR10Handler(EXCEPTION_FRAME* Frame); // Invalid TSS
|
||||
void ISR11Handler(EXCEPTION_FRAME* Frame); // Segment Not Present
|
||||
void ISR12Handler(EXCEPTION_FRAME* Frame); // Stack Segment Fault
|
||||
void ISR13Handler(EXCEPTION_FRAME* Frame); // General Protection Fault
|
||||
void ISR14Handler(EXCEPTION_FRAME* Frame); // Page Fault
|
||||
void ISR15Handler(INTERRUPT_FRAME* Frame); // Unknown Interrupt
|
||||
void ISR16Handler(INTERRUPT_FRAME* Frame); // Math Error / Coprocessor Fault
|
||||
void ISR17Handler(EXCEPTION_FRAME* Frame); // Alignment Error
|
||||
void ISR18Handler(INTERRUPT_FRAME* Frame); // Machine Check
|
||||
void ISR19Handler(INTERRUPT_FRAME* Frame); // SSE Math Error
|
||||
void ISR19Handler(INTERRUPT_FRAME* Frame); // Virtualization Exception
|
||||
void ISR20Handler(EXCEPTION_FRAME* Frame); // Security Fault
|
||||
|
||||
/* ==================== Interrupt Support ==================== */
|
||||
|
||||
void DumpRegisters_ISR(INTERRUPT_FRAME* Frame);
|
||||
void DumpRegisters_Error(EXCEPTION_FRAME* Frame);
|
||||
void DumpRegisters_AVX(XSAVE_AREA* Area);
|
||||
void DumpControlRegisters(void);
|
||||
void DumpFileloaderParams(FILELOADER_PARAMS* FLOP);
|
||||
void DumpSegmentRegisters(void);
|
||||
|
||||
void irq_install_handler(int irq, void (*handler)(INTERRUPT_FRAME* r));
|
||||
void irq_uninstall_handler(int);
|
||||
void irq_install();
|
||||
void irq_remap();
|
||||
void timer_install();
|
||||
|
||||
/* ==================== Memory ==================== */
|
||||
|
||||
uint8_t VerifyZero(size_t Length, size_t Start);
|
||||
|
||||
size_t FetchMemoryLimit(void);
|
||||
size_t FetchVisibleMemory(void);
|
||||
size_t FetchAvailableMemory(void);
|
||||
size_t FetchAvailablePMemory(void);
|
||||
size_t FetchInstalledMemory(void);
|
||||
|
||||
void PrintMemoryMap();
|
||||
|
||||
EFI_MEMORY_DESCRIPTOR* SetIdentityMap(EFI_RUNTIME_SERVICES* RT);
|
||||
void InstallMemoryMap(void);
|
||||
|
||||
void ReclaimEfiBootServicesMemory(void);
|
||||
void ReclaimEfiLoaderCodeMemory(void);
|
||||
|
||||
void MergeFragmentedMemory(void);
|
||||
|
||||
EFI_PHYSICAL_ADDRESS PurgeAllMemory(void);
|
||||
EFI_PHYSICAL_ADDRESS AllocatePagetable(size_t PagetableSize);
|
||||
|
||||
/* Physical Addresses */
|
||||
__attribute__((malloc)) void* kalloc(size_t Length);
|
||||
__attribute__((malloc)) void* kalloc_16(size_t Length);
|
||||
__attribute__((malloc)) void* kalloc_32(size_t Length);
|
||||
__attribute__((malloc)) void* kalloc_64(size_t Length);
|
||||
__attribute__((malloc)) void* kalloc_pages(size_t Pages);
|
||||
|
||||
EFI_PHYSICAL_ADDRESS FindFreeAddress(size_t Pages, EFI_PHYSICAL_ADDRESS Start);
|
||||
EFI_PHYSICAL_ADDRESS FindFreeAddress_ByPage(size_t Pages, EFI_PHYSICAL_ADDRESS Start);
|
||||
|
||||
/* The _ByXBytes functions here try to align the allocated space to the specified size. */
|
||||
EFI_PHYSICAL_ADDRESS AllocateFreeAddress_ByPage(size_t Pages, EFI_PHYSICAL_ADDRESS Start);
|
||||
EFI_PHYSICAL_ADDRESS AllocateFreeAddress_By16Bytes(size_t Bytes, EFI_PHYSICAL_ADDRESS Start);
|
||||
EFI_PHYSICAL_ADDRESS AllocateFreeAddress_By32Bytes(size_t Bytes, EFI_PHYSICAL_ADDRESS Start);
|
||||
EFI_PHYSICAL_ADDRESS AllocateFreeAddress_By64Bytes(size_t Bytes, EFI_PHYSICAL_ADDRESS Start);
|
||||
|
||||
/* Virtual Addresses */
|
||||
|
||||
__attribute__((malloc)) void* valloc(size_t Length);
|
||||
__attribute__((malloc)) void* valloc_16(size_t Length);
|
||||
__attribute__((malloc)) void* valloc_32(size_t Length);
|
||||
__attribute__((malloc)) void* valloc_64(size_t Length);
|
||||
__attribute__((malloc)) void* valloc_pages(size_t Pages);
|
||||
|
||||
EFI_VIRTUAL_ADDRESS FindVirtualAddress(size_t Pages, EFI_VIRTUAL_ADDRESS Start);
|
||||
EFI_VIRTUAL_ADDRESS FindVirtualAddress_ByPage(size_t Pages, EFI_VIRTUAL_ADDRESS Start);
|
||||
|
||||
EFI_VIRTUAL_ADDRESS AllocateVirtualAddress_ByPage(size_t Pages, EFI_VIRTUAL_ADDRESS Start);
|
||||
EFI_VIRTUAL_ADDRESS AllocateVirtualAddress_By16Bytes(size_t Pages, EFI_VIRTUAL_ADDRESS Start);
|
||||
EFI_VIRTUAL_ADDRESS AllocateVirtualAddress_By32Bytes(size_t Pages, EFI_VIRTUAL_ADDRESS Start);
|
||||
EFI_VIRTUAL_ADDRESS AllocateVirtualAddress_By64Bytes(size_t Pages, EFI_VIRTUAL_ADDRESS Start);
|
||||
|
||||
/* ==================== Graphics ==================== */
|
||||
|
||||
void ClearScreen(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU);
|
||||
void FillScreen(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU, uint32_t Color);
|
||||
|
||||
void ResetDefaultScreenColor(void);
|
||||
void ResetDefaultScreen(void);
|
||||
|
||||
void DrawPixel(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
uint32_t Color);
|
||||
|
||||
void BitmapSetup(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
||||
const uint8_t* Bitmap,
|
||||
uint32_t Height,
|
||||
uint32_t BitWidth,
|
||||
uint32_t FontColor,
|
||||
uint32_t HighlightColor,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
uint32_t Scale);
|
||||
|
||||
void BitmapRender(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
||||
const uint8_t* BitMap,
|
||||
uint32_t Height,
|
||||
uint32_t BitWidth,
|
||||
uint32_t FontColor,
|
||||
uint32_t HighlightColor,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
uint32_t Scale,
|
||||
uint32_t Character);
|
||||
|
||||
void BitmapBitswap(const uint8_t* BitMap,
|
||||
uint32_t Height,
|
||||
uint32_t BitWidth,
|
||||
uint8_t* Out);
|
||||
|
||||
void BitmapReverse(const uint8_t* BitMap,
|
||||
uint32_t Height,
|
||||
uint32_t BitWidth,
|
||||
uint8_t* Out);
|
||||
|
||||
void BitmapMirror(const uint8_t* BitMap,
|
||||
uint32_t Height,
|
||||
uint32_t BitWidth,
|
||||
uint8_t* Out);
|
||||
|
||||
|
||||
/* ========== Text ========== */
|
||||
|
||||
void SetupPrinting(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU);
|
||||
|
||||
void WriteChar(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
||||
int Char,
|
||||
uint32_t Height,
|
||||
uint32_t Width,
|
||||
uint32_t FontColor,
|
||||
uint32_t HighlightColor);
|
||||
|
||||
void WriteCharPos(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
||||
int Char,
|
||||
uint32_t Height,
|
||||
uint32_t Width,
|
||||
uint32_t FontColor,
|
||||
uint32_t HighlightColor,
|
||||
uint32_t x,
|
||||
uint32_t y);
|
||||
|
||||
void WriteScaledChar(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
||||
int Char,
|
||||
uint32_t Height,
|
||||
uint32_t Width,
|
||||
uint32_t FontColor,
|
||||
uint32_t HighlightColor,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
uint32_t Scale);
|
||||
|
||||
void WriteScaledString(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
||||
const char* string,
|
||||
uint32_t Height,
|
||||
uint32_t Width,
|
||||
uint32_t FontColor,
|
||||
uint32_t HighlightColor,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
uint32_t Scale);
|
||||
|
||||
void WriteScaledFormatString(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
||||
uint32_t Height,
|
||||
uint32_t Width,
|
||||
uint32_t FontColor,
|
||||
uint32_t HighlightColor,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
uint32_t Scale,
|
||||
const char* String,
|
||||
...);
|
||||
|
||||
void RenderText(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
||||
int Char,
|
||||
uint32_t Height,
|
||||
uint32_t Width,
|
||||
uint32_t FontColor,
|
||||
uint32_t HighlightColor,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
uint32_t Scale,
|
||||
uint32_t Index);
|
||||
|
||||
|
||||
/* ==================== Printf ==================== */
|
||||
|
||||
int snprintf(char* String, size_t Length, const char* Format, ...);
|
||||
int vsnprintf(char* String, size_t Length, const char* Format, va_list AP);
|
||||
int vsnrprintf(char* String, size_t Length, int Radix, const char* Format, va_list AP);
|
||||
int sprintf(char* Buffer, const char* Format, ...);
|
||||
int vsprintf(char* Buffer, const char* Format, va_list AP);
|
||||
|
||||
int printf(const char* Format, ...);
|
||||
int vprintf(const char* Format, va_list AP);
|
||||
int kvprintf(const char* Format, void (*func)(int, void*), void* Args, int Radix, va_list AP);
|
||||
|
||||
void PrintUTF16AsUTF8(CHAR16* String, size_t Length);
|
||||
char* UTF16ToUTF8(CHAR16* String, size_t Length);
|
||||
void panic(char*);
|
||||
|
||||
void gdb_end();
|
161
include/kernel/descriptor_tables.h
Executable file
161
include/kernel/descriptor_tables.h
Executable file
|
@ -0,0 +1,161 @@
|
|||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void gdt_set_gate(int, uint32_t, uint32_t, uint8_t, uint8_t);
|
||||
void gdt_install();
|
||||
|
||||
struct gdt_item {
|
||||
uint16_t low_limit;
|
||||
uint16_t low_base;
|
||||
uint8_t middle_base;
|
||||
uint8_t access;
|
||||
uint8_t granular;
|
||||
uint8_t high_base;
|
||||
} __attribute__((packed)); //Prevent compiler optimisation by packing
|
||||
|
||||
struct gdt_ptr {
|
||||
uint16_t limit;
|
||||
unsigned int base;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct gdt_item gdt[3]; //3-entry gdt
|
||||
struct gdt_ptr gp;
|
||||
|
||||
extern void load_gdt();
|
||||
|
||||
void idt_set_gate(unsigned char, unsigned long, unsigned short, unsigned char);
|
||||
void idt_install();
|
||||
|
||||
struct idt_entry {
|
||||
unsigned short base_low;
|
||||
unsigned short selector;
|
||||
unsigned char always0;
|
||||
unsigned char flags;
|
||||
unsigned short base_high;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct idt_ptr {
|
||||
unsigned short limit;
|
||||
unsigned int base;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct idt_entry idt[256]; //interrupt table of 256 entries
|
||||
struct idt_ptr idtp; //pointer to idt table
|
||||
|
||||
struct int_frame {
|
||||
void (*eip) (void);
|
||||
uint16_t cs, :16;
|
||||
uint32_t eflags;
|
||||
void* esp;
|
||||
uint16_t ss, :16;
|
||||
} __attribute__((packed));
|
||||
|
||||
void isr_common(struct int_frame*, size_t);
|
||||
|
||||
void isr_error_common(struct int_frame*, size_t, size_t);
|
||||
|
||||
void irq_common(struct int_frame*, size_t);
|
||||
|
||||
extern void idt_load();
|
||||
|
||||
//These are all reserved by Intel, and need to be here.
|
||||
extern void isr0();
|
||||
extern void isr1();
|
||||
extern void isr2();
|
||||
extern void isr3();
|
||||
extern void isr4();
|
||||
extern void isr5();
|
||||
extern void isr6();
|
||||
extern void isr7();
|
||||
extern void isr8();
|
||||
extern void isr9();
|
||||
extern void isr10();
|
||||
extern void isr11();
|
||||
extern void isr12();
|
||||
extern void isr13();
|
||||
extern void isr14();
|
||||
extern void isr15();
|
||||
extern void isr16();
|
||||
extern void isr17();
|
||||
extern void isr18();
|
||||
extern void isr19();
|
||||
extern void isr20();
|
||||
extern void isr21();
|
||||
extern void isr22();
|
||||
extern void isr23();
|
||||
extern void isr24();
|
||||
extern void isr25();
|
||||
extern void isr26();
|
||||
extern void isr27();
|
||||
extern void isr28();
|
||||
extern void isr29();
|
||||
extern void isr30();
|
||||
extern void isr31();
|
||||
|
||||
extern void irq0();
|
||||
extern void irq1();
|
||||
extern void irq2();
|
||||
extern void irq3();
|
||||
extern void irq4();
|
||||
extern void irq5();
|
||||
extern void irq6();
|
||||
extern void irq7();
|
||||
extern void irq8();
|
||||
extern void irq9();
|
||||
extern void irq10();
|
||||
extern void irq11();
|
||||
extern void irq12();
|
||||
extern void irq13();
|
||||
extern void irq14();
|
||||
extern void irq15();
|
||||
|
||||
static void* irq_routines[16] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
void irq_install_handler(int irq, void (*handler)(struct int_frame* r));
|
||||
|
||||
void irq_uninstall_handler(int);
|
||||
|
||||
void irq_install();
|
||||
|
||||
void irq_remap();
|
||||
|
||||
void timer_install();
|
||||
|
||||
static const char* exception_messages[] = {
|
||||
"Division by Zero",
|
||||
"Debug",
|
||||
"Non Maskable Interrupt",
|
||||
"Breakpoint",
|
||||
"Into Detected Overflow",
|
||||
"Out of Bounds",
|
||||
"Invalid Opcode",
|
||||
"No Coprocessor",
|
||||
"Double Fault",
|
||||
"Coprocessor Segment Overrun",
|
||||
"Bad TSS",
|
||||
"Segment Not Present",
|
||||
"Stack Fault",
|
||||
"General Protection Fault",
|
||||
"Page Fault",
|
||||
"Unknown Interrupt",
|
||||
"Coprocessor Fault",
|
||||
"Alignment Check",
|
||||
"Machine Check",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved"
|
||||
};
|
278
include/kernel/multiboot.h
Normal file
278
include/kernel/multiboot.h
Normal file
|
@ -0,0 +1,278 @@
|
|||
/* multiboot.h - Multiboot header file. */
|
||||
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
|
||||
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MULTIBOOT_HEADER
|
||||
#define MULTIBOOT_HEADER 1
|
||||
|
||||
/* How many bytes from the start of the file we search for the header. */
|
||||
#define MULTIBOOT_SEARCH 8192
|
||||
#define MULTIBOOT_HEADER_ALIGN 4
|
||||
|
||||
/* The magic field should contain this. */
|
||||
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
|
||||
|
||||
/* This should be in %eax. */
|
||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
|
||||
|
||||
/* Alignment of multiboot modules. */
|
||||
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
||||
|
||||
/* Alignment of the multiboot info structure. */
|
||||
#define MULTIBOOT_INFO_ALIGN 0x00000004
|
||||
|
||||
/* Flags set in the 'flags' member of the multiboot header. */
|
||||
|
||||
/* Align all boot modules on i386 page (4KB) boundaries. */
|
||||
#define MULTIBOOT_PAGE_ALIGN 0x00000001
|
||||
|
||||
/* Must pass memory information to OS. */
|
||||
#define MULTIBOOT_MEMORY_INFO 0x00000002
|
||||
|
||||
/* Must pass video information to OS. */
|
||||
#define MULTIBOOT_VIDEO_MODE 0x00000004
|
||||
|
||||
/* This flag indicates the use of the address fields in the header. */
|
||||
#define MULTIBOOT_AOUT_KLUDGE 0x00010000
|
||||
|
||||
/* Flags to be set in the 'flags' member of the multiboot info structure. */
|
||||
|
||||
/* is there basic lower/upper memory information? */
|
||||
#define MULTIBOOT_INFO_MEMORY 0x00000001
|
||||
/* is there a boot device set? */
|
||||
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
|
||||
/* is the command-line defined? */
|
||||
#define MULTIBOOT_INFO_CMDLINE 0x00000004
|
||||
/* are there modules to do something with? */
|
||||
#define MULTIBOOT_INFO_MODS 0x00000008
|
||||
|
||||
/* These next two are mutually exclusive */
|
||||
|
||||
/* is there a symbol table loaded? */
|
||||
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
|
||||
/* is there an ELF section header table? */
|
||||
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
|
||||
|
||||
/* is there a full memory map? */
|
||||
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
|
||||
|
||||
/* Is there drive info? */
|
||||
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
|
||||
|
||||
/* Is there a config table? */
|
||||
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
|
||||
|
||||
/* Is there a boot loader name? */
|
||||
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
|
||||
|
||||
/* Is there a APM table? */
|
||||
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
|
||||
|
||||
/* Is there video information? */
|
||||
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
|
||||
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
|
||||
|
||||
#ifndef ASM_FILE
|
||||
|
||||
typedef unsigned char multiboot_uint8_t;
|
||||
typedef unsigned short multiboot_uint16_t;
|
||||
typedef unsigned int multiboot_uint32_t;
|
||||
typedef unsigned long long multiboot_uint64_t;
|
||||
|
||||
struct multiboot_header
|
||||
{
|
||||
/* Must be MULTIBOOT_MAGIC - see above. */
|
||||
multiboot_uint32_t magic;
|
||||
|
||||
/* Feature flags. */
|
||||
multiboot_uint32_t flags;
|
||||
|
||||
/* The above fields plus this one must equal 0 mod 2^32. */
|
||||
multiboot_uint32_t checksum;
|
||||
|
||||
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
|
||||
multiboot_uint32_t header_addr;
|
||||
multiboot_uint32_t load_addr;
|
||||
multiboot_uint32_t load_end_addr;
|
||||
multiboot_uint32_t bss_end_addr;
|
||||
multiboot_uint32_t entry_addr;
|
||||
|
||||
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
|
||||
multiboot_uint32_t mode_type;
|
||||
multiboot_uint32_t width;
|
||||
multiboot_uint32_t height;
|
||||
multiboot_uint32_t depth;
|
||||
};
|
||||
|
||||
/* The symbol table for a.out. */
|
||||
struct multiboot_aout_symbol_table
|
||||
{
|
||||
multiboot_uint32_t tabsize;
|
||||
multiboot_uint32_t strsize;
|
||||
multiboot_uint32_t addr;
|
||||
multiboot_uint32_t reserved;
|
||||
};
|
||||
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
|
||||
|
||||
/* The section header table for ELF. */
|
||||
struct multiboot_elf_section_header_table
|
||||
{
|
||||
multiboot_uint32_t num;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t addr;
|
||||
multiboot_uint32_t shndx;
|
||||
};
|
||||
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
|
||||
|
||||
struct multiboot_info
|
||||
{
|
||||
/* Multiboot info version number */
|
||||
multiboot_uint32_t flags;
|
||||
|
||||
/* Available memory from BIOS */
|
||||
multiboot_uint32_t mem_lower;
|
||||
multiboot_uint32_t mem_upper;
|
||||
|
||||
/* "root" partition */
|
||||
multiboot_uint32_t boot_device;
|
||||
|
||||
/* Kernel command line */
|
||||
multiboot_uint32_t cmdline;
|
||||
|
||||
/* Boot-Module list */
|
||||
multiboot_uint32_t mods_count;
|
||||
multiboot_uint32_t mods_addr;
|
||||
|
||||
union
|
||||
{
|
||||
multiboot_aout_symbol_table_t aout_sym;
|
||||
multiboot_elf_section_header_table_t elf_sec;
|
||||
} u;
|
||||
|
||||
/* Memory Mapping buffer */
|
||||
multiboot_uint32_t mmap_length;
|
||||
multiboot_uint32_t mmap_addr;
|
||||
|
||||
/* Drive Info buffer */
|
||||
multiboot_uint32_t drives_length;
|
||||
multiboot_uint32_t drives_addr;
|
||||
|
||||
/* ROM configuration table */
|
||||
multiboot_uint32_t config_table;
|
||||
|
||||
/* Boot Loader Name */
|
||||
multiboot_uint32_t boot_loader_name;
|
||||
|
||||
/* APM table */
|
||||
multiboot_uint32_t apm_table;
|
||||
|
||||
/* Video */
|
||||
multiboot_uint32_t vbe_control_info;
|
||||
multiboot_uint32_t vbe_mode_info;
|
||||
multiboot_uint16_t vbe_mode;
|
||||
multiboot_uint16_t vbe_interface_seg;
|
||||
multiboot_uint16_t vbe_interface_off;
|
||||
multiboot_uint16_t vbe_interface_len;
|
||||
|
||||
multiboot_uint64_t framebuffer_addr;
|
||||
multiboot_uint32_t framebuffer_pitch;
|
||||
multiboot_uint32_t framebuffer_width;
|
||||
multiboot_uint32_t framebuffer_height;
|
||||
multiboot_uint8_t framebuffer_bpp;
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
|
||||
multiboot_uint8_t framebuffer_type;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
multiboot_uint32_t framebuffer_palette_addr;
|
||||
multiboot_uint16_t framebuffer_palette_num_colors;
|
||||
};
|
||||
struct
|
||||
{
|
||||
multiboot_uint8_t framebuffer_red_field_position;
|
||||
multiboot_uint8_t framebuffer_red_mask_size;
|
||||
multiboot_uint8_t framebuffer_green_field_position;
|
||||
multiboot_uint8_t framebuffer_green_mask_size;
|
||||
multiboot_uint8_t framebuffer_blue_field_position;
|
||||
multiboot_uint8_t framebuffer_blue_mask_size;
|
||||
};
|
||||
};
|
||||
};
|
||||
typedef struct multiboot_info multiboot_info_t;
|
||||
|
||||
struct multiboot_color
|
||||
{
|
||||
multiboot_uint8_t red;
|
||||
multiboot_uint8_t green;
|
||||
multiboot_uint8_t blue;
|
||||
};
|
||||
|
||||
struct multiboot_mmap_entry
|
||||
{
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint64_t addr;
|
||||
multiboot_uint64_t len;
|
||||
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
||||
#define MULTIBOOT_MEMORY_RESERVED 2
|
||||
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
||||
#define MULTIBOOT_MEMORY_NVS 4
|
||||
#define MULTIBOOT_MEMORY_BADRAM 5
|
||||
multiboot_uint32_t type;
|
||||
} __attribute__((packed));
|
||||
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
||||
|
||||
struct multiboot_mod_list
|
||||
{
|
||||
/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
|
||||
multiboot_uint32_t mod_start;
|
||||
multiboot_uint32_t mod_end;
|
||||
|
||||
/* Module command line */
|
||||
multiboot_uint32_t cmdline;
|
||||
|
||||
/* padding to take it to 16 bytes (must be zero) */
|
||||
multiboot_uint32_t pad;
|
||||
};
|
||||
typedef struct multiboot_mod_list multiboot_module_t;
|
||||
|
||||
/* APM BIOS info. */
|
||||
struct multiboot_apm_info
|
||||
{
|
||||
multiboot_uint16_t version;
|
||||
multiboot_uint16_t cseg;
|
||||
multiboot_uint32_t offset;
|
||||
multiboot_uint16_t cseg_16;
|
||||
multiboot_uint16_t dseg;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint16_t cseg_len;
|
||||
multiboot_uint16_t cseg_16_len;
|
||||
multiboot_uint16_t dseg_len;
|
||||
};
|
||||
|
||||
#endif /* ! ASM_FILE */
|
||||
|
||||
#endif /* ! MULTIBOOT_HEADER */
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,390 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) 1998 Intel Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
efefind.h
|
||||
|
||||
Abstract:
|
||||
|
||||
EFI to compile bindings
|
||||
|
||||
|
||||
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
#ifndef X86_64_EFI_BIND
|
||||
#define X86_64_EFI_BIND
|
||||
#ifndef __GNUC__
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#if defined(GNU_EFI_USE_MS_ABI)
|
||||
#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))||(defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 2)))
|
||||
#define HAVE_USE_MS_ABI 1
|
||||
#else
|
||||
#error Compiler is too old for GNU_EFI_USE_MS_ABI
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// Basic int types of various widths
|
||||
//
|
||||
|
||||
#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )
|
||||
|
||||
// No ANSI C 1999/2000 stdint.h integer width declarations
|
||||
|
||||
#if defined(_MSC_EXTENSIONS)
|
||||
|
||||
// Use Microsoft C compiler integer width declarations
|
||||
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef char int8_t;
|
||||
#elif defined(__GNUC__)
|
||||
typedef int __attribute__((__mode__(__DI__))) int64_t;
|
||||
typedef unsigned int __attribute__((__mode__(__DI__))) uint64_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
#elif defined(UNIX_LP64)
|
||||
|
||||
/* Use LP64 programming model from C_FLAGS for integer width declarations */
|
||||
|
||||
typedef unsigned long uint64_t;
|
||||
typedef long int64_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef char int8_t;
|
||||
#else
|
||||
|
||||
/* Assume P64 programming model from C_FLAGS for integer width declarations */
|
||||
|
||||
typedef unsigned long long uint64_t __attribute__((aligned (8)));
|
||||
typedef long long int64_t __attribute__((aligned (8)));
|
||||
typedef unsigned int uint32_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef char int8_t;
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
//
|
||||
// Basic EFI types of various widths
|
||||
//
|
||||
|
||||
#ifndef __WCHAR_TYPE__
|
||||
# define __WCHAR_TYPE__ short
|
||||
#endif
|
||||
|
||||
typedef uint64_t UINT64;
|
||||
typedef int64_t INT64;
|
||||
|
||||
#ifndef _BASETSD_H_
|
||||
typedef uint32_t UINT32;
|
||||
typedef int32_t INT32;
|
||||
#endif
|
||||
|
||||
typedef uint16_t UINT16;
|
||||
typedef int16_t INT16;
|
||||
typedef uint8_t UINT8;
|
||||
typedef int8_t INT8;
|
||||
typedef __WCHAR_TYPE__ WCHAR;
|
||||
|
||||
#undef VOID
|
||||
#define VOID void
|
||||
|
||||
|
||||
typedef int64_t INTN;
|
||||
typedef uint64_t UINTN;
|
||||
|
||||
#ifdef EFI_NT_EMULATOR
|
||||
#define POST_CODE(_Data)
|
||||
#else
|
||||
#ifdef EFI_DEBUG
|
||||
#define POST_CODE(_Data) __asm mov eax,(_Data) __asm out 0x80,al
|
||||
#else
|
||||
#define POST_CODE(_Data)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define EFIERR(a) (0x8000000000000000 | a)
|
||||
#define EFI_ERROR_MASK 0x8000000000000000
|
||||
#define EFIERR_OEM(a) (0xc000000000000000 | a)
|
||||
|
||||
|
||||
#define BAD_POINTER 0xFBFBFBFBFBFBFBFB
|
||||
#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF
|
||||
|
||||
#ifdef EFI_NT_EMULATOR
|
||||
#define BREAKPOINT() __asm { int 3 }
|
||||
#else
|
||||
#define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32
|
||||
#endif
|
||||
|
||||
//
|
||||
// Pointers must be aligned to these address to function
|
||||
//
|
||||
|
||||
#define MIN_ALIGNMENT_SIZE 4
|
||||
|
||||
#define ALIGN_VARIABLE(Value ,Adjustment) \
|
||||
(UINTN)Adjustment = 0; \
|
||||
if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
|
||||
(UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \
|
||||
Value = (UINTN)Value + (UINTN)Adjustment
|
||||
|
||||
|
||||
//
|
||||
// Define macros to build data structure signatures from characters.
|
||||
//
|
||||
|
||||
#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8))
|
||||
#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16))
|
||||
#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
|
||||
//
|
||||
// To export & import functions in the EFI emulator environment
|
||||
//
|
||||
|
||||
#ifdef EFI_NT_EMULATOR
|
||||
#define EXPORTAPI __declspec( dllexport )
|
||||
#else
|
||||
#define EXPORTAPI
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// EFIAPI - prototype calling convention for EFI function pointers
|
||||
// BOOTSERVICE - prototype for implementation of a boot service interface
|
||||
// RUNTIMESERVICE - prototype for implementation of a runtime service interface
|
||||
// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service
|
||||
// RUNTIME_CODE - pragma macro for declaring runtime code
|
||||
//
|
||||
|
||||
#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options
|
||||
#ifdef _MSC_EXTENSIONS
|
||||
#define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler
|
||||
#elif defined(HAVE_USE_MS_ABI)
|
||||
// Force amd64/ms calling conventions.
|
||||
#define EFIAPI __attribute__((ms_abi))
|
||||
#else
|
||||
#define EFIAPI // Substitute expresion to force C calling convention
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BOOTSERVICE
|
||||
//#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a
|
||||
//#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a
|
||||
#define RUNTIMESERVICE
|
||||
#define RUNTIMEFUNCTION
|
||||
|
||||
|
||||
#define RUNTIME_CODE(a) alloc_text("rtcode", a)
|
||||
#define BEGIN_RUNTIME_DATA() data_seg("rtdata")
|
||||
#define END_RUNTIME_DATA() data_seg("")
|
||||
|
||||
#define VOLATILE volatile
|
||||
|
||||
#define MEMORY_FENCE()
|
||||
|
||||
#ifdef EFI_NT_EMULATOR
|
||||
|
||||
//
|
||||
// To help ensure proper coding of integrated drivers, they are
|
||||
// compiled as DLLs. In NT they require a dll init entry pointer.
|
||||
// The macro puts a stub entry point into the DLL so it will load.
|
||||
//
|
||||
|
||||
#define EFI_DRIVER_ENTRY_POINT(InitFunction) \
|
||||
UINTN \
|
||||
__stdcall \
|
||||
_DllMainCRTStartup ( \
|
||||
UINTN Inst, \
|
||||
UINTN reason_for_call, \
|
||||
VOID *rserved \
|
||||
) \
|
||||
{ \
|
||||
return 1; \
|
||||
} \
|
||||
\
|
||||
int \
|
||||
EXPORTAPI \
|
||||
__cdecl \
|
||||
InitializeDriver ( \
|
||||
void *ImageHandle, \
|
||||
void *SystemTable \
|
||||
) \
|
||||
{ \
|
||||
return InitFunction(ImageHandle, SystemTable); \
|
||||
}
|
||||
|
||||
|
||||
#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \
|
||||
(_if)->LoadInternal(type, name, NULL)
|
||||
|
||||
#else // EFI_NT_EMULATOR
|
||||
|
||||
//
|
||||
// When build similiar to FW, then link everything together as
|
||||
// one big module. For the MSVC toolchain, we simply tell the
|
||||
// linker what our driver init function is using /ENTRY.
|
||||
//
|
||||
#if defined(_MSC_EXTENSIONS)
|
||||
#define EFI_DRIVER_ENTRY_POINT(InitFunction) \
|
||||
__pragma(comment(linker, "/ENTRY:" # InitFunction))
|
||||
#else
|
||||
#define EFI_DRIVER_ENTRY_POINT(InitFunction) \
|
||||
UINTN \
|
||||
InitializeDriver ( \
|
||||
VOID *ImageHandle, \
|
||||
VOID *SystemTable \
|
||||
) \
|
||||
{ \
|
||||
return InitFunction(ImageHandle, \
|
||||
SystemTable); \
|
||||
} \
|
||||
\
|
||||
EFI_STATUS efi_main( \
|
||||
EFI_HANDLE image, \
|
||||
EFI_SYSTEM_TABLE *systab \
|
||||
) __attribute__((weak, \
|
||||
alias ("InitializeDriver")));
|
||||
#endif
|
||||
|
||||
#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \
|
||||
(_if)->LoadInternal(type, name, entry)
|
||||
|
||||
#endif // EFI_NT_EMULATOR
|
||||
|
||||
//
|
||||
// Some compilers don't support the forward reference construct:
|
||||
// typedef struct XXXXX
|
||||
//
|
||||
// The following macro provide a workaround for such cases.
|
||||
//
|
||||
#ifdef NO_INTERFACE_DECL
|
||||
#define INTERFACE_DECL(x)
|
||||
#else
|
||||
#if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
|
||||
#define INTERFACE_DECL(x) struct x
|
||||
#else
|
||||
#define INTERFACE_DECL(x) typedef struct x
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* for x86_64, EFI_FUNCTION_WRAPPER must be defined */
|
||||
#if defined(HAVE_USE_MS_ABI)
|
||||
#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__)
|
||||
#else
|
||||
/*
|
||||
Credits for macro-magic:
|
||||
https://groups.google.com/forum/?fromgroups#!topic/comp.std.c/d-6Mj5Lko_s
|
||||
http://efesx.com/2010/08/31/overloading-macros/
|
||||
*/
|
||||
#define __VA_NARG__(...) \
|
||||
__VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N())
|
||||
#define __VA_NARG_(...) \
|
||||
__VA_ARG_N(__VA_ARGS__)
|
||||
#define __VA_ARG_N( \
|
||||
_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N
|
||||
#define __RSEQ_N() \
|
||||
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
#define __VA_ARG_NSUFFIX__(prefix,...) \
|
||||
__VA_ARG_NSUFFIX_N(prefix, __VA_NARG__(__VA_ARGS__))
|
||||
#define __VA_ARG_NSUFFIX_N(prefix,nargs) \
|
||||
__VA_ARG_NSUFFIX_N_(prefix, nargs)
|
||||
#define __VA_ARG_NSUFFIX_N_(prefix,nargs) \
|
||||
prefix ## nargs
|
||||
|
||||
/* Prototypes of EFI cdecl -> stdcall trampolines */
|
||||
UINT64 efi_call0(void *func);
|
||||
UINT64 efi_call1(void *func, UINT64 arg1);
|
||||
UINT64 efi_call2(void *func, UINT64 arg1, UINT64 arg2);
|
||||
UINT64 efi_call3(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3);
|
||||
UINT64 efi_call4(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
|
||||
UINT64 arg4);
|
||||
UINT64 efi_call5(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
|
||||
UINT64 arg4, UINT64 arg5);
|
||||
UINT64 efi_call6(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
|
||||
UINT64 arg4, UINT64 arg5, UINT64 arg6);
|
||||
UINT64 efi_call7(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
|
||||
UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7);
|
||||
UINT64 efi_call8(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
|
||||
UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7,
|
||||
UINT64 arg8);
|
||||
UINT64 efi_call9(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
|
||||
UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7,
|
||||
UINT64 arg8, UINT64 arg9);
|
||||
UINT64 efi_call10(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
|
||||
UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7,
|
||||
UINT64 arg8, UINT64 arg9, UINT64 arg10);
|
||||
|
||||
/* Front-ends to efi_callX to avoid compiler warnings */
|
||||
#define _cast64_efi_call0(f) \
|
||||
efi_call0(f)
|
||||
#define _cast64_efi_call1(f,a1) \
|
||||
efi_call1(f, (UINT64)(a1))
|
||||
#define _cast64_efi_call2(f,a1,a2) \
|
||||
efi_call2(f, (UINT64)(a1), (UINT64)(a2))
|
||||
#define _cast64_efi_call3(f,a1,a2,a3) \
|
||||
efi_call3(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3))
|
||||
#define _cast64_efi_call4(f,a1,a2,a3,a4) \
|
||||
efi_call4(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4))
|
||||
#define _cast64_efi_call5(f,a1,a2,a3,a4,a5) \
|
||||
efi_call5(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
|
||||
(UINT64)(a5))
|
||||
#define _cast64_efi_call6(f,a1,a2,a3,a4,a5,a6) \
|
||||
efi_call6(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
|
||||
(UINT64)(a5), (UINT64)(a6))
|
||||
#define _cast64_efi_call7(f,a1,a2,a3,a4,a5,a6,a7) \
|
||||
efi_call7(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
|
||||
(UINT64)(a5), (UINT64)(a6), (UINT64)(a7))
|
||||
#define _cast64_efi_call8(f,a1,a2,a3,a4,a5,a6,a7,a8) \
|
||||
efi_call8(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
|
||||
(UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8))
|
||||
#define _cast64_efi_call9(f,a1,a2,a3,a4,a5,a6,a7,a8,a9) \
|
||||
efi_call9(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
|
||||
(UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \
|
||||
(UINT64)(a9))
|
||||
#define _cast64_efi_call10(f,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \
|
||||
efi_call10(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
|
||||
(UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \
|
||||
(UINT64)(a9), (UINT64)(a10))
|
||||
|
||||
/* main wrapper (va_num ignored) */
|
||||
#define uefi_call_wrapper(func,va_num,...) \
|
||||
__VA_ARG_NSUFFIX__(_cast64_efi_call, __VA_ARGS__) (func , ##__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_USE_MS_ABI) && !defined(_MSC_EXTENSIONS)
|
||||
#define EFI_FUNCTION __attribute__((ms_abi))
|
||||
#else
|
||||
#define EFI_FUNCTION
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_EXTENSIONS
|
||||
#pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,67 +0,0 @@
|
|||
#ifndef _EFI_ERR_H
|
||||
#define _EFI_ERR_H
|
||||
|
||||
/*++
|
||||
|
||||
Copyright (c) 1998 Intel Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
efierr.h
|
||||
|
||||
Abstract:
|
||||
|
||||
EFI error codes
|
||||
|
||||
|
||||
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#define EFIWARN(a) (a)
|
||||
#define EFI_ERROR(a) (((INTN) a) < 0)
|
||||
|
||||
|
||||
#define EFI_SUCCESS 0
|
||||
#define EFI_LOAD_ERROR EFIERR(1)
|
||||
#define EFI_INVALID_PARAMETER EFIERR(2)
|
||||
#define EFI_UNSUPPORTED EFIERR(3)
|
||||
#define EFI_BAD_BUFFER_SIZE EFIERR(4)
|
||||
#define EFI_BUFFER_TOO_SMALL EFIERR(5)
|
||||
#define EFI_NOT_READY EFIERR(6)
|
||||
#define EFI_DEVICE_ERROR EFIERR(7)
|
||||
#define EFI_WRITE_PROTECTED EFIERR(8)
|
||||
#define EFI_OUT_OF_RESOURCES EFIERR(9)
|
||||
#define EFI_VOLUME_CORRUPTED EFIERR(10)
|
||||
#define EFI_VOLUME_FULL EFIERR(11)
|
||||
#define EFI_NO_MEDIA EFIERR(12)
|
||||
#define EFI_MEDIA_CHANGED EFIERR(13)
|
||||
#define EFI_NOT_FOUND EFIERR(14)
|
||||
#define EFI_ACCESS_DENIED EFIERR(15)
|
||||
#define EFI_NO_RESPONSE EFIERR(16)
|
||||
#define EFI_NO_MAPPING EFIERR(17)
|
||||
#define EFI_TIMEOUT EFIERR(18)
|
||||
#define EFI_NOT_STARTED EFIERR(19)
|
||||
#define EFI_ALREADY_STARTED EFIERR(20)
|
||||
#define EFI_ABORTED EFIERR(21)
|
||||
#define EFI_ICMP_ERROR EFIERR(22)
|
||||
#define EFI_TFTP_ERROR EFIERR(23)
|
||||
#define EFI_PROTOCOL_ERROR EFIERR(24)
|
||||
#define EFI_INCOMPATIBLE_VERSION EFIERR(25)
|
||||
#define EFI_SECURITY_VIOLATION EFIERR(26)
|
||||
#define EFI_CRC_ERROR EFIERR(27)
|
||||
#define EFI_END_OF_MEDIA EFIERR(28)
|
||||
#define EFI_END_OF_FILE EFIERR(31)
|
||||
#define EFI_INVALID_LANGUAGE EFIERR(32)
|
||||
#define EFI_COMPROMISED_DATA EFIERR(33)
|
||||
|
||||
#define EFI_WARN_UNKOWN_GLYPH EFIWARN(1)
|
||||
#define EFI_WARN_DELETE_FAILURE EFIWARN(2)
|
||||
#define EFI_WARN_WRITE_FAILURE EFIWARN(3)
|
||||
#define EFI_WARN_BUFFER_TOO_SMALL EFIWARN(4)
|
||||
|
||||
#endif
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
EfiTypes.h
|
||||
|
||||
Abstract:
|
||||
|
||||
EFI defined types. Use these types when ever possible!
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _EFI_TYPES_H_
|
||||
#define _EFI_TYPES_H_
|
||||
|
||||
//
|
||||
// EFI Data Types based on ANSI C integer types in EfiBind.h
|
||||
//
|
||||
typedef uint8_t BOOLEAN;
|
||||
typedef int64_t INTN;
|
||||
typedef uint64_t UINTN;
|
||||
typedef int8_t INT8;
|
||||
typedef uint8_t UINT8;
|
||||
typedef int16_t INT16;
|
||||
typedef uint16_t UINT16;
|
||||
typedef int32_t INT32;
|
||||
typedef uint32_t UINT32;
|
||||
typedef int64_t INT64;
|
||||
typedef uint64_t UINT64;
|
||||
typedef char CHAR8;
|
||||
typedef uint16_t CHAR16;
|
||||
typedef UINT64 EFI_LBA;
|
||||
|
||||
//
|
||||
// Modifiers for EFI Data Types used to self document code.
|
||||
// Please see EFI coding convention for proper usage.
|
||||
//
|
||||
#ifndef IN
|
||||
//
|
||||
// Some other envirnments use this construct, so #ifndef to prevent
|
||||
// mulitple definition.
|
||||
//
|
||||
#define IN
|
||||
#define OUT
|
||||
#define OPTIONAL
|
||||
#endif
|
||||
|
||||
#ifndef UNALIGNED
|
||||
#define UNALIGNED
|
||||
#endif
|
||||
|
||||
//
|
||||
// Modifiers for EFI Runtime and Boot Services
|
||||
//
|
||||
#define EFI_RUNTIMESERVICE
|
||||
#define EFI_BOOTSERVICE
|
||||
|
||||
//
|
||||
// Boot Service add in EFI 1.1
|
||||
//
|
||||
#define EFI_BOOTSERVICE11
|
||||
|
||||
//
|
||||
// Modifiers to absract standard types to aid in debug of problems
|
||||
//
|
||||
#define CONST const
|
||||
#define STATIC static
|
||||
#define VOID void
|
||||
#define VOLATILE volatile
|
||||
|
||||
//
|
||||
// Modifier to ensure that all protocol member functions and EFI intrinsics
|
||||
// use the correct C calling convention. All protocol member functions and
|
||||
// EFI intrinsics are required to modify thier member functions with EFIAPI.
|
||||
//
|
||||
#ifndef EFIAPI
|
||||
#define EFIAPI _EFIAPI
|
||||
#endif
|
||||
|
||||
//
|
||||
// EFI Constants. They may exist in other build structures, so #ifndef them.
|
||||
//
|
||||
#ifndef TRUE
|
||||
#define TRUE ((BOOLEAN) (1 == 1))
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE ((BOOLEAN) (0 == 1))
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((VOID *) 0)
|
||||
#endif
|
||||
//
|
||||
// EFI Data Types derived from other EFI data types.
|
||||
//
|
||||
typedef UINTN EFI_STATUS;
|
||||
|
||||
typedef VOID *EFI_HANDLE;
|
||||
#define NULL_HANDLE ((VOID *) 0)
|
||||
|
||||
typedef VOID *EFI_EVENT;
|
||||
typedef UINTN EFI_TPL;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Data1;
|
||||
UINT16 Data2;
|
||||
UINT16 Data3;
|
||||
UINT8 Data4[8];
|
||||
} EFI_GUID;
|
||||
|
||||
typedef union {
|
||||
EFI_GUID Guid;
|
||||
UINT8 Raw[16];
|
||||
} EFI_GUID_UNION;
|
||||
|
||||
//
|
||||
// EFI Time Abstraction:
|
||||
// Year: 2000 - 20XX
|
||||
// Month: 1 - 12
|
||||
// Day: 1 - 31
|
||||
// Hour: 0 - 23
|
||||
// Minute: 0 - 59
|
||||
// Second: 0 - 59
|
||||
// Nanosecond: 0 - 999,999,999
|
||||
// TimeZone: -1440 to 1440 or 2047
|
||||
//
|
||||
typedef struct {
|
||||
UINT16 Year;
|
||||
UINT8 Month;
|
||||
UINT8 Day;
|
||||
UINT8 Hour;
|
||||
UINT8 Minute;
|
||||
UINT8 Second;
|
||||
UINT8 Pad1;
|
||||
UINT32 Nanosecond;
|
||||
INT16 TimeZone;
|
||||
UINT8 Daylight;
|
||||
UINT8 Pad2;
|
||||
} EFI_TIME;
|
||||
|
||||
//
|
||||
// Bit definitions for EFI_TIME.Daylight
|
||||
//
|
||||
#define EFI_TIME_ADJUST_DAYLIGHT 0x01
|
||||
#define EFI_TIME_IN_DAYLIGHT 0x02
|
||||
|
||||
//
|
||||
// Value definition for EFI_TIME.TimeZone
|
||||
//
|
||||
#define EFI_UNSPECIFIED_TIMEZONE 0x07FF
|
||||
|
||||
//
|
||||
// Networking
|
||||
//
|
||||
typedef struct {
|
||||
UINT8 Addr[4];
|
||||
} EFI_IPv4_ADDRESS;
|
||||
|
||||
typedef struct {
|
||||
UINT8 Addr[16];
|
||||
} EFI_IPv6_ADDRESS;
|
||||
|
||||
typedef struct {
|
||||
UINT8 Addr[32];
|
||||
} EFI_MAC_ADDRESS;
|
||||
|
||||
typedef union {
|
||||
UINT32 Addr[4];
|
||||
EFI_IPv4_ADDRESS v4;
|
||||
EFI_IPv6_ADDRESS v6;
|
||||
} EFI_IP_ADDRESS;
|
||||
|
||||
typedef enum {
|
||||
EfiReservedMemoryType,
|
||||
EfiLoaderCode,
|
||||
EfiLoaderData,
|
||||
EfiBootServicesCode,
|
||||
EfiBootServicesData,
|
||||
EfiRuntimeServicesCode,
|
||||
EfiRuntimeServicesData,
|
||||
EfiConventionalMemory,
|
||||
EfiUnusableMemory,
|
||||
EfiACPIReclaimMemory,
|
||||
EfiACPIMemoryNVS,
|
||||
EfiMemoryMappedIO,
|
||||
EfiMemoryMappedIOPortSpace,
|
||||
EfiPalCode,
|
||||
EfiPersistentMemory,
|
||||
EfiMaxMemoryType
|
||||
} EFI_MEMORY_TYPE;
|
||||
|
||||
typedef enum {
|
||||
AllocateAnyPages,
|
||||
AllocateMaxAddress,
|
||||
AllocateAddress,
|
||||
MaxAllocateType
|
||||
} EFI_ALLOCATE_TYPE;
|
||||
|
||||
typedef struct {
|
||||
UINT64 Signature;
|
||||
UINT32 Revision;
|
||||
UINT32 HeaderSize;
|
||||
UINT32 CRC32;
|
||||
UINT32 Reserved;
|
||||
} EFI_TABLE_HEADER;
|
||||
|
||||
//
|
||||
// possible caching types for the memory range
|
||||
//
|
||||
#define EFI_MEMORY_UC 0x0000000000000001
|
||||
#define EFI_MEMORY_WC 0x0000000000000002
|
||||
#define EFI_MEMORY_WT 0x0000000000000004
|
||||
#define EFI_MEMORY_WB 0x0000000000000008
|
||||
#define EFI_MEMORY_UCE 0x0000000000000010
|
||||
|
||||
//
|
||||
// physical memory protection on range
|
||||
//
|
||||
#define EFI_MEMORY_WP 0x0000000000001000
|
||||
#define EFI_MEMORY_RP 0x0000000000002000
|
||||
#define EFI_MEMORY_XP 0x0000000000004000
|
||||
|
||||
//
|
||||
// range requires a runtime mapping
|
||||
//
|
||||
#define EFI_MEMORY_RUNTIME 0x8000000000000000ULL
|
||||
|
||||
typedef UINT64 EFI_PHYSICAL_ADDRESS;
|
||||
typedef UINT64 EFI_VIRTUAL_ADDRESS;
|
||||
|
||||
#define EFI_MEMORY_DESCRIPTOR_VERSION 1
|
||||
typedef struct {
|
||||
UINT32 Type;
|
||||
UINT32 Pad;
|
||||
EFI_PHYSICAL_ADDRESS PhysicalStart;
|
||||
EFI_VIRTUAL_ADDRESS VirtualStart;
|
||||
UINT64 NumberOfPages;
|
||||
UINT64 Attribute;
|
||||
} EFI_MEMORY_DESCRIPTOR;
|
||||
|
||||
//
|
||||
// The EFI memory allocation functions work in units of EFI_PAGEs that are
|
||||
// 4K. This should in no way be confused with the page size of the processor.
|
||||
// An EFI_PAGE is just the quanta of memory in EFI.
|
||||
//
|
||||
#define EFI_PAGE_SIZE 4096
|
||||
#define EFI_PAGE_MASK 0xFFF
|
||||
#define EFI_PAGE_SHIFT 12
|
||||
|
||||
#define EFI_SIZE_TO_PAGES(a) (((a) >> EFI_PAGE_SHIFT) + (((a) & EFI_PAGE_MASK) ? 1 : 0))
|
||||
|
||||
#define EFI_PAGES_TO_SIZE(a) ( (a) << EFI_PAGE_SHIFT)
|
||||
|
||||
//
|
||||
// ALIGN_POINTER - aligns a pointer to the lowest boundary
|
||||
//
|
||||
#define ALIGN_POINTER(p, s) ((VOID *) (p + ((s - ((UINTN) p)) & (s - 1))))
|
||||
|
||||
//
|
||||
// ALIGN_VARIABLE - aligns a variable up to the next natural boundary for int size of a processor
|
||||
//
|
||||
#define ALIGN_VARIABLE(Value, Adjustment) \
|
||||
(UINTN) Adjustment = 0; \
|
||||
if ((UINTN) Value % sizeof (UINTN)) { \
|
||||
(UINTN) Adjustment = sizeof (UINTN) - ((UINTN) Value % sizeof (UINTN)); \
|
||||
} \
|
||||
Value = (UINTN) Value + (UINTN) Adjustment
|
||||
|
||||
//
|
||||
// EFI_FIELD_OFFSET - returns the byte offset to a field within a structure
|
||||
//
|
||||
#define EFI_FIELD_OFFSET(TYPE,Field) ((UINTN)(&(((TYPE *) 0)->Field)))
|
||||
|
||||
//
|
||||
// CONTAINING_RECORD - returns a pointer to the structure
|
||||
// from one of it's elements.
|
||||
//
|
||||
#define _CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
|
||||
|
||||
//
|
||||
// Define macros to build data structure signatures from characters.
|
||||
//
|
||||
#define EFI_SIGNATURE_16(A, B) ((A) | (B << 8))
|
||||
#define EFI_SIGNATURE_32(A, B, C, D) (EFI_SIGNATURE_16 (A, B) | (EFI_SIGNATURE_16 (C, D) << 16))
|
||||
#define EFI_SIGNATURE_64(A, B, C, D, E, F, G, H) \
|
||||
(EFI_SIGNATURE_32 (A, B, C, D) | ((UINT64) (EFI_SIGNATURE_32 (E, F, G, H)) << 32))
|
||||
|
||||
#endif
|
7
iso/boot/grub/grub.cfg
Normal file
7
iso/boot/grub/grub.cfg
Normal file
|
@ -0,0 +1,7 @@
|
|||
set timeout=10
|
||||
set default=0
|
||||
|
||||
menuentry "ProjectRED" {
|
||||
multiboot /boot/red.kernel
|
||||
boot
|
||||
}
|
5
iso/boot/grub/menu.lst
Executable file
5
iso/boot/grub/menu.lst
Executable file
|
@ -0,0 +1,5 @@
|
|||
defualt=0
|
||||
timeout=0
|
||||
|
||||
title ProjectRED
|
||||
kernel /boot/kernel.elf
|
BIN
iso/boot/grub/stage2_eltorito
Executable file
BIN
iso/boot/grub/stage2_eltorito
Executable file
Binary file not shown.
|
@ -1,98 +0,0 @@
|
|||
/************************
|
||||
*** Team Kitty, 2019 ***
|
||||
*** Sync ***
|
||||
***********************/
|
||||
|
||||
/* This file contains all of the functions required to handle
|
||||
* the system handover from Syncboot.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
|
||||
static void UpdateSegments(void);
|
||||
static void InstallInterrupt(size_t ISR, size_t Function);
|
||||
static void InstallTrap(size_t ISR, size_t Function);
|
||||
|
||||
|
||||
|
||||
/* Main system handover from UEFI.
|
||||
* Prepares the processor, the screen, and memory. */
|
||||
void PrepareSystem(FILELOADER_PARAMS* FLOP) {
|
||||
Memory_Info.MemoryMap = FLOP->MemoryMap;
|
||||
Memory_Info.MemoryMapSize = FLOP->MemoryMap_Size;
|
||||
Memory_Info.MemoryMapDescriptorSize = FLOP->MemoryMapDescriptorSize;
|
||||
Memory_Info.MemoryMapDescriptorVersion = FLOP->MemoryMapDescriptorVersion;
|
||||
|
||||
if(SetIdentityMap(FLOP->RTServices) == NULL) {
|
||||
Memory_Info.MemoryMap = FLOP->MemoryMap;
|
||||
}
|
||||
|
||||
SetupPrinting(FLOP->GPU_Info->GPUs[0]);
|
||||
/* All print functions are now available. */
|
||||
|
||||
PrepareAVX();
|
||||
|
||||
|
||||
|
||||
/* Bit 5 of CR0 is Numeric Error, which enables
|
||||
* the internal x87 Floating Point Math error
|
||||
* reporting. */
|
||||
size_t CR0 = ReadControlRegister(0);
|
||||
// Mask CR0 to only see bit 5
|
||||
if( !(CR0 & (1 << 5))) {
|
||||
// Preserve CR0, but set bit 5.
|
||||
size_t TempReg = CR0 ^ (1 << 5);
|
||||
// Write it back
|
||||
WriteControlRegister(0, TempReg);
|
||||
|
||||
// Double check. Some processors can be tricky.
|
||||
TempReg = ReadControlRegister(CR0);
|
||||
if(TempReg == CR0)
|
||||
printf("Error setting CR0.NE\r\n");
|
||||
|
||||
}
|
||||
|
||||
/* Bit 10 of CR4 is OSXMMEXCPT, which enables
|
||||
* SSE instructions. */
|
||||
size_t CR4 = ReadControlRegister(4);
|
||||
// Mask CR4 to only see bit 10
|
||||
if( !(CR4 & (1 << 10))) {
|
||||
// Preserve CR4, but set bit 10.
|
||||
size_t TempReg = CR4 ^ (1 << 10);
|
||||
// Write it back
|
||||
WriteControlRegister(4, TempReg);
|
||||
|
||||
// Double check. Some processors can be tricky.
|
||||
TempReg = ReadControlRegister(4);
|
||||
if(TempReg == CR4)
|
||||
printf("Error setting CR4.OSXMMEXCPT\r\n");
|
||||
}
|
||||
|
||||
// Set up memory management
|
||||
InstallGDT();
|
||||
InstallIDT();
|
||||
InstallMemoryMap();
|
||||
InstallPaging();
|
||||
|
||||
// Clean up UEFI's mess
|
||||
ReclaimEfiBootServicesMemory();
|
||||
ReclaimEfiLoaderCodeMemory();
|
||||
|
||||
// Let Intel ME take over power management
|
||||
PreparePowerManagement();
|
||||
|
||||
}
|
||||
|
||||
/* A temporary system for keeping track of system performance. */
|
||||
|
||||
size_t ClockTick() {
|
||||
|
||||
// We will be reading a register, so we need to split it up.
|
||||
size_t RegHigh = 0, RegLow = 0;
|
||||
|
||||
__asm__ __volatile__("rdtscp" : "=a" (RegLow), "=d" (RegHigh) : : "%rcx");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3,84 +3,88 @@
|
|||
*** Sync ***
|
||||
***********************/
|
||||
|
||||
/*
|
||||
* Sync main..
|
||||
*
|
||||
* Going off the back of Syncboot, the UEFI bootloader which currently only supports x86_64,
|
||||
* this kernel is to be rewritten. The kernel is started in Long Mode, with interrupts enabled.
|
||||
*
|
||||
* Therefore, most of the checks are no longer needed, as they are performed by Syncboot for us.
|
||||
* So, this becomes an exercise in time saving.
|
||||
*
|
||||
/* This file contains the entry point
|
||||
* to the kernel. This section consists
|
||||
* mainly of bootloading functions.
|
||||
*
|
||||
* Graphics and memory will be setup
|
||||
* at later stages.
|
||||
*/
|
||||
|
||||
//#include <stdio.h>
|
||||
#include <kernel.h>
|
||||
#include <kernel/tty.h>
|
||||
#include <kernel/serial.h>
|
||||
#include <kernel/descriptor_tables.h>
|
||||
|
||||
void gdb_end() {} /* GDB Debugging stump */
|
||||
|
||||
int kernel_main(void) {
|
||||
/* The kernel is started in 64-bit Long Mode by Syncboot. */
|
||||
/* Here, we start by drawing a splash, then loading a GDT and IDT into the placeholder UEFI gives us. */
|
||||
|
||||
/* The kernel is started in 32-bit protected mode by the ASM. */
|
||||
/* Here, we start by enabling the screen, then loading a GDT and IDT into the actual places they need to be. */
|
||||
|
||||
/* Not sure how well serial would work in UEFI. */
|
||||
// TODO: look at this.
|
||||
|
||||
//init_serial();
|
||||
//serial_print(0x3F8, "[INFO] Serial ready.\r\n");
|
||||
/* Black the screen out. */
|
||||
screen_initialize();
|
||||
|
||||
/* Prepare the serial line for our debug output. */
|
||||
init_serial();
|
||||
serial_print(0x3F8, "[INFO] Serial ready.\r\n");
|
||||
|
||||
|
||||
//serial_print(0x3F8, "[INFO] Beginning GDT subroutine.\r\n");
|
||||
serial_print(0x3F8, "[INFO] Beginning GDT subroutine.\r\n");
|
||||
|
||||
/* term_writes: writes a string to the terminal. */
|
||||
//term_writes("GDT...");
|
||||
term_writes("GDT...");
|
||||
|
||||
/* Prepares the Global Descriptor Table, called from gdt.c */
|
||||
gdt_install();
|
||||
|
||||
/* puts: writes a line to the terminal. */
|
||||
//puts("GDT Ready.");
|
||||
//serial_print(0x3F8, "[INFO] GDT subroutine complete.\r\n");
|
||||
puts("GDT Ready.");
|
||||
serial_print(0x3F8, "[INFO] GDT subroutine complete.\r\n");
|
||||
|
||||
/* Prepare the Interrupt Descriptor Table. */
|
||||
//serial_print(0x3F8, "[INFO] Beginning IDT subroutine.\r\n");
|
||||
//term_writes("IDT...");
|
||||
serial_print(0x3F8, "[INFO] Beginning IDT subroutine.\r\n");
|
||||
term_writes("IDT...");
|
||||
idt_install();
|
||||
//puts("IDT Ready.");
|
||||
//serial_print(0x3F8, "[INFO] IDT subroutine complete.\r\n[INFO] Enabling interrupts.\r\n");
|
||||
puts("IDT Ready.");
|
||||
serial_print(0x3F8, "[INFO] IDT subroutine complete.\r\n[INFO] Enabling interrupts.\r\n");
|
||||
|
||||
gdb_end(); /* The first important step. Waypoint it for gdb debugging. */
|
||||
|
||||
//term_writes("Memory available:");
|
||||
term_writes("Memory available:");
|
||||
/* TODO: implement check_a20, which double-triple checks the state of the A20 line. */
|
||||
|
||||
//if(check_a20())
|
||||
puts(" 4GB");
|
||||
serial_print(0x3F8, "[INFO] A20 enabled. 4GB memory available.");
|
||||
|
||||
/* The first important thing: start the system clock immediately. */
|
||||
//serial_print(0x3F8, "[INFO] Starting System Clock.\r\n");
|
||||
//term_writes("Timer...");
|
||||
serial_print(0x3F8, "[INFO] Starting System Clock.\r\n");
|
||||
term_writes("Timer...");
|
||||
timer_install();
|
||||
//puts("Timer Ready.");
|
||||
puts("Timer Ready.");
|
||||
|
||||
//serial_print(0x3F8, "[INFO] All subsystems ready. Printing message.\r\n");
|
||||
serial_print(0x3F8, "[INFO] All subsystems ready. Printing message.\r\n");
|
||||
|
||||
/* Everything is ready; print a pretty message. */
|
||||
//term_setcolor(RED);
|
||||
//term_writes("\n(c)");
|
||||
//term_setcolor(GREEN);
|
||||
//term_writes(" Sync");
|
||||
//term_setcolor(WHITE);
|
||||
//term_writes(", 2019\n");
|
||||
term_setcolor(RED);
|
||||
term_writes("\n(c)");
|
||||
term_setcolor(GREEN);
|
||||
term_writes(" Sync");
|
||||
term_setcolor(WHITE);
|
||||
term_writes(", 2019\n");
|
||||
|
||||
//serial_print(0x3F8, "[INFO] All operations complete. Checking for other tasks...\r\n");
|
||||
serial_print(0x3F8, "[INFO] All operations complete. Checking for other tasks...\r\n");
|
||||
|
||||
/* Here are a series of tests for the ANSI escape code and CSI implementations. */
|
||||
//term_writes("\x1b[BA"); /* Down a line, then A. */
|
||||
term_writes("\x1b[BA"); /* Down a line, then A. */
|
||||
|
||||
|
||||
/* A stub causing a Divide by Zero error. */
|
||||
//serial_print(0x3F8, "[DEBUG] Attempting a Divide by Zero error.\r\n");
|
||||
//char div = (5 / 0);
|
||||
//serial_print(0x3F8, "[DEBUG] Survived the error!\r\n");
|
||||
serial_print(0x3F8, "[DEBUG] Attempting a Divide by Zero error.\r\n");
|
||||
char div = (5 / 0);
|
||||
serial_print(0x3F8, "[DEBUG] Survived the error!\r\n");
|
||||
|
||||
gdb_end(); /* Everything is done. The last debug routine. */
|
||||
return 0;
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
* a text buffer, or a file, but this code should work on
|
||||
* hardware with an actual serial port and monitor. */
|
||||
|
||||
/* After the development of Syncboot, this becomes a little bit harder.
|
||||
* Some testing will be needed to know for certain whether this will work.
|
||||
* Until then, this is to be put on hold. 21/07/19 - Curle */
|
||||
|
||||
#include <kernel/utils.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
|
3
libc/.gitignore
vendored
Executable file
3
libc/.gitignore
vendored
Executable file
|
@ -0,0 +1,3 @@
|
|||
*.a
|
||||
*.d
|
||||
*.o
|
91
libc/Makefile
Executable file
91
libc/Makefile
Executable file
|
@ -0,0 +1,91 @@
|
|||
DEFAULT_HOST!=../default-host.sh
|
||||
HOST?=DEFAULT_HOST
|
||||
HOSTARCH!==../target-to-arch.sh $(HOST)
|
||||
|
||||
CFLAGS?=-O2 -g
|
||||
CPPFLAGS?=
|
||||
LDFLAGS?=
|
||||
LIBS?=
|
||||
|
||||
DESTDIR?=
|
||||
PREFIX?=/usr/local
|
||||
EXEC_PREFIX?=$(PREFIX)
|
||||
INCLUDEDIR?=$(PREFIX)/include
|
||||
LIBDIR?=$(EXEC_PREFIX)/lib
|
||||
|
||||
CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra
|
||||
CPPFLAGS:=$(CPPFLAGS) -D__is_libc -Iinclude
|
||||
LIBK_CFLAGS:=$(CFLAGS)
|
||||
LIBK_CPPFLAGS:=$(CPPFLAGS) -D__is_libk
|
||||
|
||||
ARCHDIR=arch/$(HOSTARCH)
|
||||
|
||||
include $(ARCHDIR)/make.config
|
||||
|
||||
CFLAGS:=$(CFLAGS) $(ARCH_CFLAGS)
|
||||
CPPFLAGS:=$(CPPFLAGS) $(ARCH_CPPFLAGS)
|
||||
LIBK_CFLAGS:=$(LIBK_CFLAGS) $(KERNEL_ARCH_CFLAGS)
|
||||
LIBK_CPPFLAGS:=$(LIBK_CPPFLAGS) $(KERNEL_ARCH_CPPFLAGS)
|
||||
|
||||
FREEOBJS=\
|
||||
$(ARCH_FREEOBJS)\
|
||||
stdio/printf.o\
|
||||
stdio/putchar.o\
|
||||
stdio/puts.o\
|
||||
stdlib/abort.o\
|
||||
string/memcmp.o\
|
||||
string/memcpy.o\
|
||||
string/memmove.o\
|
||||
string/memset.o\
|
||||
string/strlen.o\
|
||||
|
||||
HOSTEDOBJS=\
|
||||
$(ARCH_HOSTEDOBJS)\
|
||||
|
||||
OBJS=\
|
||||
$(FREEOBJS)\
|
||||
$(HOSTEDOBJS)\
|
||||
|
||||
LIBK_OBJS=$(FREEOBJS:.o=.libk.o)
|
||||
|
||||
BINARIES=libk.a
|
||||
|
||||
.PHONY: all clean install install-headers install-libs
|
||||
.SUFFIXES: .o .libk.o .c .s
|
||||
|
||||
all: $(BINARIES)
|
||||
|
||||
libc.a: $(OBJS)
|
||||
$(AR) rcs $@ $(OBJS)
|
||||
libk.a: $(LIBK_OBJS)
|
||||
$(AR) rcs $@ $(LIBK_OBJS)
|
||||
|
||||
.c.o:
|
||||
$(CC) -MD -c $< -o $@ -std=gnull $(CFLAGS) $(CPPFLAGS)
|
||||
|
||||
.c.s:
|
||||
$(CC) -MD -c $< -o $@ $(CFLAGS) $(CPPFLAGS)
|
||||
.c.libk.o:
|
||||
$(CC) -MD -c $< -o $@ -std=gnull $(LIBK_CFLAGS) $(LIBK_CPPFLAGS)
|
||||
.s.libk.o:
|
||||
$(CC) -MD -c $< -o $@ $(LIBK_CFLAGS) $(LIBK_CPPFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f $(BINARIES) *.a
|
||||
rm -f $(OBJS) $(LIBK_OBJS) *.o */*.o */*/*.o
|
||||
rm -f $(OBJS:.o=.d) $(LIBK_OBJS:.o=.d) *.d */*.d */*/*.d
|
||||
|
||||
install: install-headers install-libs
|
||||
|
||||
install-headers:
|
||||
mkdir -p $(DESTDIR)$(INCLUDEDIR)
|
||||
cp -R --preserve-timestamps include/. $(DESTDIR)$(INCLUDEDIR)/.
|
||||
install-libs: $(BINARIES)
|
||||
mkdir -p $(DESTDIR)$(LIBDIR)
|
||||
cp $(BINARIES) $(DESTDIR) $(LIBDIR)
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
-include $(LIBK_OBJS:.o=.d)
|
||||
|
||||
|
||||
|
8
libc/arch/i386/make.config
Executable file
8
libc/arch/i386/make.config
Executable file
|
@ -0,0 +1,8 @@
|
|||
ARCH_CFLAGS=
|
||||
ARCH_CPPFLAGS=
|
||||
KERNEL_ARCH_CFLAGS=
|
||||
KERNEL_ARCH_CPPFLAGS=
|
||||
|
||||
ARCH_FREEOBJS=\
|
||||
|
||||
ARCH_HOSTEDOBJS=\
|
0
libc/include/errno.h
Executable file
0
libc/include/errno.h
Executable file
19
libc/include/stdio.h
Executable file
19
libc/include/stdio.h
Executable file
|
@ -0,0 +1,19 @@
|
|||
#ifndef _STDIO_H
|
||||
#define _STDIO_H 1
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#define EOF (-1)
|
||||
|
||||
struct __sFile {
|
||||
int unused;
|
||||
};
|
||||
|
||||
typedef struct __sFile FILE;
|
||||
|
||||
#define stderr (_impure_ptr->_stderr)
|
||||
|
||||
int printf(const char* __restrict, ...);
|
||||
int putchar(int);
|
||||
int puts(const char*);
|
||||
#endif
|
594
libc/include/stdlib.h
Normal file
594
libc/include/stdlib.h
Normal file
|
@ -0,0 +1,594 @@
|
|||
#ifndef _STDLIB_H
|
||||
#define _STDLIB_H 1
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__attribute__((__noreturn__)) void abort(void);
|
||||
|
||||
/*
|
||||
Default header file for malloc-2.8.x, written by Doug Lea
|
||||
and released to the public domain, as explained at
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
This header is for ANSI C/C++ only. You can set any of
|
||||
the following #defines before including:
|
||||
|
||||
* If USE_DL_PREFIX is defined, it is assumed that malloc.c
|
||||
was also compiled with this option, so all routines
|
||||
have names starting with "dl".
|
||||
|
||||
* If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this
|
||||
file will be #included AFTER <malloc.h>. This is needed only if
|
||||
your system defines a struct mallinfo that is incompatible with the
|
||||
standard one declared here. Otherwise, you can include this file
|
||||
INSTEAD of your system system <malloc.h>. At least on ANSI, all
|
||||
declarations should be compatible with system versions
|
||||
|
||||
* If MSPACES is defined, declarations for mspace versions are included.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
#ifndef ONLY_MSPACES
|
||||
#define ONLY_MSPACES 0 /* define to a value */
|
||||
#elif ONLY_MSPACES != 0
|
||||
#define ONLY_MSPACES 1
|
||||
#endif /* ONLY_MSPACES */
|
||||
#ifndef NO_MALLINFO
|
||||
#define NO_MALLINFO 0
|
||||
#endif /* NO_MALLINFO */
|
||||
|
||||
#ifndef MSPACES
|
||||
#if ONLY_MSPACES
|
||||
#define MSPACES 1
|
||||
#else /* ONLY_MSPACES */
|
||||
#define MSPACES 0
|
||||
#endif /* ONLY_MSPACES */
|
||||
#endif /* MSPACES */
|
||||
|
||||
#if !ONLY_MSPACES
|
||||
|
||||
#if !NO_MALLINFO
|
||||
#ifndef HAVE_USR_INCLUDE_MALLOC_H
|
||||
#ifndef _MALLOC_H
|
||||
#ifndef MALLINFO_FIELD_TYPE
|
||||
#define MALLINFO_FIELD_TYPE size_t
|
||||
#endif /* MALLINFO_FIELD_TYPE */
|
||||
#ifndef STRUCT_MALLINFO_DECLARED
|
||||
#define STRUCT_MALLINFO_DECLARED 1
|
||||
struct mallinfo {
|
||||
MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */
|
||||
MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */
|
||||
MALLINFO_FIELD_TYPE smblks; /* always 0 */
|
||||
MALLINFO_FIELD_TYPE hblks; /* always 0 */
|
||||
MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */
|
||||
MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */
|
||||
MALLINFO_FIELD_TYPE fsmblks; /* always 0 */
|
||||
MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
|
||||
MALLINFO_FIELD_TYPE fordblks; /* total free space */
|
||||
MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
|
||||
};
|
||||
#endif /* STRUCT_MALLINFO_DECLARED */
|
||||
#endif /* _MALLOC_H */
|
||||
#endif /* HAVE_USR_INCLUDE_MALLOC_H */
|
||||
#endif /* !NO_MALLINFO */
|
||||
|
||||
/*
|
||||
malloc(size_t n)
|
||||
Returns a pointer to a newly allocated chunk of at least n bytes, or
|
||||
null if no space is available, in which case errno is set to ENOMEM
|
||||
on ANSI C systems.
|
||||
|
||||
If n is zero, malloc returns a minimum-sized chunk. (The minimum
|
||||
size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
|
||||
systems.) Note that size_t is an unsigned type, so calls with
|
||||
arguments that would be negative if signed are interpreted as
|
||||
requests for huge amounts of space, which will often fail. The
|
||||
maximum supported value of n differs across systems, but is in all
|
||||
cases less than the maximum representable value of a size_t.
|
||||
*/
|
||||
void* malloc(size_t);
|
||||
|
||||
/*
|
||||
free(void* p)
|
||||
Releases the chunk of memory pointed to by p, that had been previously
|
||||
allocated using malloc or a related routine such as realloc.
|
||||
It has no effect if p is null. If p was not malloced or already
|
||||
freed, free(p) will by default cuase the current program to abort.
|
||||
*/
|
||||
void free(void*);
|
||||
|
||||
/*
|
||||
calloc(size_t n_elements, size_t element_size);
|
||||
Returns a pointer to n_elements * element_size bytes, with all locations
|
||||
set to zero.
|
||||
*/
|
||||
void* calloc(size_t, size_t);
|
||||
|
||||
/*
|
||||
realloc(void* p, size_t n)
|
||||
Returns a pointer to a chunk of size n that contains the same data
|
||||
as does chunk p up to the minimum of (n, p's size) bytes, or null
|
||||
if no space is available.
|
||||
|
||||
The returned pointer may or may not be the same as p. The algorithm
|
||||
prefers extending p in most cases when possible, otherwise it
|
||||
employs the equivalent of a malloc-copy-free sequence.
|
||||
|
||||
If p is null, realloc is equivalent to malloc.
|
||||
|
||||
If space is not available, realloc returns null, errno is set (if on
|
||||
ANSI) and p is NOT freed.
|
||||
|
||||
if n is for fewer bytes than already held by p, the newly unused
|
||||
space is lopped off and freed if possible. realloc with a size
|
||||
argument of zero (re)allocates a minimum-sized chunk.
|
||||
|
||||
The old unix realloc convention of allowing the last-free'd chunk
|
||||
to be used as an argument to realloc is not supported.
|
||||
*/
|
||||
void* realloc(void*, size_t);
|
||||
|
||||
/*
|
||||
realloc_in_place(void* p, size_t n)
|
||||
Resizes the space allocated for p to size n, only if this can be
|
||||
done without moving p (i.e., only if there is adjacent space
|
||||
available if n is greater than p's current allocated size, or n is
|
||||
less than or equal to p's size). This may be used instead of plain
|
||||
realloc if an alternative allocation strategy is needed upon failure
|
||||
to expand space; for example, reallocation of a buffer that must be
|
||||
memory-aligned or cleared. You can use realloc_in_place to trigger
|
||||
these alternatives only when needed.
|
||||
|
||||
Returns p if successful; otherwise null.
|
||||
*/
|
||||
void* realloc_in_place(void*, size_t);
|
||||
|
||||
/*
|
||||
memalign(size_t alignment, size_t n);
|
||||
Returns a pointer to a newly allocated chunk of n bytes, aligned
|
||||
in accord with the alignment argument.
|
||||
|
||||
The alignment argument should be a power of two. If the argument is
|
||||
not a power of two, the nearest greater power is used.
|
||||
8-byte alignment is guaranteed by normal malloc calls, so don't
|
||||
bother calling memalign with an argument of 8 or less.
|
||||
|
||||
Overreliance on memalign is a sure way to fragment space.
|
||||
*/
|
||||
void* memalign(size_t, size_t);
|
||||
|
||||
/*
|
||||
int posix_memalign(void** pp, size_t alignment, size_t n);
|
||||
Allocates a chunk of n bytes, aligned in accord with the alignment
|
||||
argument. Differs from memalign only in that it (1) assigns the
|
||||
allocated memory to *pp rather than returning it, (2) fails and
|
||||
returns EINVAL if the alignment is not a power of two (3) fails and
|
||||
returns ENOMEM if memory cannot be allocated.
|
||||
*/
|
||||
int posix_memalign(void**, size_t, size_t);
|
||||
|
||||
/*
|
||||
valloc(size_t n);
|
||||
Equivalent to memalign(pagesize, n), where pagesize is the page
|
||||
size of the system. If the pagesize is unknown, 4096 is used.
|
||||
*/
|
||||
void* valloc(size_t);
|
||||
|
||||
/*
|
||||
mallopt(int parameter_number, int parameter_value)
|
||||
Sets tunable parameters The format is to provide a
|
||||
(parameter-number, parameter-value) pair. mallopt then sets the
|
||||
corresponding parameter to the argument value if it can (i.e., so
|
||||
long as the value is meaningful), and returns 1 if successful else
|
||||
0. SVID/XPG/ANSI defines four standard param numbers for mallopt,
|
||||
normally defined in malloc.h. None of these are use in this malloc,
|
||||
so setting them has no effect. But this malloc also supports other
|
||||
options in mallopt:
|
||||
|
||||
Symbol param # default allowed param values
|
||||
M_TRIM_THRESHOLD -1 2*1024*1024 any (-1U disables trimming)
|
||||
M_GRANULARITY -2 page size any power of 2 >= page size
|
||||
M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support)
|
||||
*/
|
||||
int mallopt(int, int);
|
||||
|
||||
#define M_TRIM_THRESHOLD (-1)
|
||||
#define M_GRANULARITY (-2)
|
||||
#define M_MMAP_THRESHOLD (-3)
|
||||
|
||||
/*
|
||||
malloc_footprint();
|
||||
Returns the number of bytes obtained from the system. The total
|
||||
number of bytes allocated by malloc, realloc etc., is less than this
|
||||
value. Unlike mallinfo, this function returns only a precomputed
|
||||
result, so can be called frequently to monitor memory consumption.
|
||||
Even if locks are otherwise defined, this function does not use them,
|
||||
so results might not be up to date.
|
||||
*/
|
||||
size_t malloc_footprint(void);
|
||||
|
||||
/*
|
||||
malloc_max_footprint();
|
||||
Returns the maximum number of bytes obtained from the system. This
|
||||
value will be greater than current footprint if deallocated space
|
||||
has been reclaimed by the system. The peak number of bytes allocated
|
||||
by malloc, realloc etc., is less than this value. Unlike mallinfo,
|
||||
this function returns only a precomputed result, so can be called
|
||||
frequently to monitor memory consumption. Even if locks are
|
||||
otherwise defined, this function does not use them, so results might
|
||||
not be up to date.
|
||||
*/
|
||||
size_t malloc_max_footprint(void);
|
||||
|
||||
/*
|
||||
malloc_footprint_limit();
|
||||
Returns the number of bytes that the heap is allowed to obtain from
|
||||
the system, returning the last value returned by
|
||||
malloc_set_footprint_limit, or the maximum size_t value if
|
||||
never set. The returned value reflects a permission. There is no
|
||||
guarantee that this number of bytes can actually be obtained from
|
||||
the system.
|
||||
*/
|
||||
size_t malloc_footprint_limit(void);
|
||||
|
||||
/*
|
||||
malloc_set_footprint_limit();
|
||||
Sets the maximum number of bytes to obtain from the system, causing
|
||||
failure returns from malloc and related functions upon attempts to
|
||||
exceed this value. The argument value may be subject to page
|
||||
rounding to an enforceable limit; this actual value is returned.
|
||||
Using an argument of the maximum possible size_t effectively
|
||||
disables checks. If the argument is less than or equal to the
|
||||
current malloc_footprint, then all future allocations that require
|
||||
additional system memory will fail. However, invocation cannot
|
||||
retroactively deallocate existing used memory.
|
||||
*/
|
||||
size_t malloc_set_footprint_limit(size_t bytes);
|
||||
|
||||
/*
|
||||
malloc_inspect_all(void(*handler)(void *start,
|
||||
void *end,
|
||||
size_t used_bytes,
|
||||
void* callback_arg),
|
||||
void* arg);
|
||||
Traverses the heap and calls the given handler for each managed
|
||||
region, skipping all bytes that are (or may be) used for bookkeeping
|
||||
purposes. Traversal does not include include chunks that have been
|
||||
directly memory mapped. Each reported region begins at the start
|
||||
address, and continues up to but not including the end address. The
|
||||
first used_bytes of the region contain allocated data. If
|
||||
used_bytes is zero, the region is unallocated. The handler is
|
||||
invoked with the given callback argument. If locks are defined, they
|
||||
are held during the entire traversal. It is a bad idea to invoke
|
||||
other malloc functions from within the handler.
|
||||
|
||||
For example, to count the number of in-use chunks with size greater
|
||||
than 1000, you could write:
|
||||
static int count = 0;
|
||||
void count_chunks(void* start, void* end, size_t used, void* arg) {
|
||||
if (used >= 1000) ++count;
|
||||
}
|
||||
then:
|
||||
malloc_inspect_all(count_chunks, NULL);
|
||||
|
||||
malloc_inspect_all is compiled only if MALLOC_INSPECT_ALL is defined.
|
||||
*/
|
||||
void malloc_inspect_all(void (*handler)(void*, void*, size_t, void*), void* arg);
|
||||
|
||||
#if !NO_MALLINFO
|
||||
/*
|
||||
mallinfo()
|
||||
Returns (by copy) a struct containing various summary statistics:
|
||||
|
||||
arena: current total non-mmapped bytes allocated from system
|
||||
ordblks: the number of free chunks
|
||||
smblks: always zero.
|
||||
hblks: current number of mmapped regions
|
||||
hblkhd: total bytes held in mmapped regions
|
||||
usmblks: the maximum total allocated space. This will be greater
|
||||
than current total if trimming has occurred.
|
||||
fsmblks: always zero
|
||||
uordblks: current total allocated space (normal or mmapped)
|
||||
fordblks: total free space
|
||||
keepcost: the maximum number of bytes that could ideally be released
|
||||
back to system via malloc_trim. ("ideally" means that
|
||||
it ignores page restrictions etc.)
|
||||
|
||||
Because these fields are ints, but internal bookkeeping may
|
||||
be kept as longs, the reported values may wrap around zero and
|
||||
thus be inaccurate.
|
||||
*/
|
||||
|
||||
struct mallinfo mallinfo(void);
|
||||
#endif /* NO_MALLINFO */
|
||||
|
||||
/*
|
||||
independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
|
||||
|
||||
independent_calloc is similar to calloc, but instead of returning a
|
||||
single cleared space, it returns an array of pointers to n_elements
|
||||
independent elements that can hold contents of size elem_size, each
|
||||
of which starts out cleared, and can be independently freed,
|
||||
realloc'ed etc. The elements are guaranteed to be adjacently
|
||||
allocated (this is not guaranteed to occur with multiple callocs or
|
||||
mallocs), which may also improve cache locality in some
|
||||
applications.
|
||||
|
||||
The "chunks" argument is optional (i.e., may be null, which is
|
||||
probably the most typical usage). If it is null, the returned array
|
||||
is itself dynamically allocated and should also be freed when it is
|
||||
no longer needed. Otherwise, the chunks array must be of at least
|
||||
n_elements in length. It is filled in with the pointers to the
|
||||
chunks.
|
||||
|
||||
In either case, independent_calloc returns this pointer array, or
|
||||
null if the allocation failed. If n_elements is zero and "chunks"
|
||||
is null, it returns a chunk representing an array with zero elements
|
||||
(which should be freed if not wanted).
|
||||
|
||||
Each element must be freed when it is no longer needed. This can be
|
||||
done all at once using bulk_free.
|
||||
|
||||
independent_calloc simplifies and speeds up implementations of many
|
||||
kinds of pools. It may also be useful when constructing large data
|
||||
structures that initially have a fixed number of fixed-sized nodes,
|
||||
but the number is not known at compile time, and some of the nodes
|
||||
may later need to be freed. For example:
|
||||
|
||||
struct Node { int item; struct Node* next; };
|
||||
|
||||
struct Node* build_list() {
|
||||
struct Node** pool;
|
||||
int n = read_number_of_nodes_needed();
|
||||
if (n <= 0) return 0;
|
||||
pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
|
||||
if (pool == 0) die();
|
||||
// organize into a linked list...
|
||||
struct Node* first = pool[0];
|
||||
for (i = 0; i < n-1; ++i)
|
||||
pool[i]->next = pool[i+1];
|
||||
free(pool); // Can now free the array (or not, if it is needed later)
|
||||
return first;
|
||||
}
|
||||
*/
|
||||
void** independent_calloc(size_t, size_t, void**);
|
||||
|
||||
/*
|
||||
independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
|
||||
|
||||
independent_comalloc allocates, all at once, a set of n_elements
|
||||
chunks with sizes indicated in the "sizes" array. It returns
|
||||
an array of pointers to these elements, each of which can be
|
||||
independently freed, realloc'ed etc. The elements are guaranteed to
|
||||
be adjacently allocated (this is not guaranteed to occur with
|
||||
multiple callocs or mallocs), which may also improve cache locality
|
||||
in some applications.
|
||||
|
||||
The "chunks" argument is optional (i.e., may be null). If it is null
|
||||
the returned array is itself dynamically allocated and should also
|
||||
be freed when it is no longer needed. Otherwise, the chunks array
|
||||
must be of at least n_elements in length. It is filled in with the
|
||||
pointers to the chunks.
|
||||
|
||||
In either case, independent_comalloc returns this pointer array, or
|
||||
null if the allocation failed. If n_elements is zero and chunks is
|
||||
null, it returns a chunk representing an array with zero elements
|
||||
(which should be freed if not wanted).
|
||||
|
||||
Each element must be freed when it is no longer needed. This can be
|
||||
done all at once using bulk_free.
|
||||
|
||||
independent_comallac differs from independent_calloc in that each
|
||||
element may have a different size, and also that it does not
|
||||
automatically clear elements.
|
||||
|
||||
independent_comalloc can be used to speed up allocation in cases
|
||||
where several structs or objects must always be allocated at the
|
||||
same time. For example:
|
||||
|
||||
struct Head { ... }
|
||||
struct Foot { ... }
|
||||
|
||||
void send_message(char* msg) {
|
||||
int msglen = strlen(msg);
|
||||
size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
|
||||
void* chunks[3];
|
||||
if (independent_comalloc(3, sizes, chunks) == 0)
|
||||
die();
|
||||
struct Head* head = (struct Head*)(chunks[0]);
|
||||
char* body = (char*)(chunks[1]);
|
||||
struct Foot* foot = (struct Foot*)(chunks[2]);
|
||||
// ...
|
||||
}
|
||||
|
||||
In general though, independent_comalloc is worth using only for
|
||||
larger values of n_elements. For small values, you probably won't
|
||||
detect enough difference from series of malloc calls to bother.
|
||||
|
||||
Overuse of independent_comalloc can increase overall memory usage,
|
||||
since it cannot reuse existing noncontiguous small chunks that
|
||||
might be available for some of the elements.
|
||||
*/
|
||||
void** independent_comalloc(size_t, size_t*, void**);
|
||||
|
||||
/*
|
||||
bulk_free(void* array[], size_t n_elements)
|
||||
Frees and clears (sets to null) each non-null pointer in the given
|
||||
array. This is likely to be faster than freeing them one-by-one.
|
||||
If footers are used, pointers that have been allocated in different
|
||||
mspaces are not freed or cleared, and the count of all such pointers
|
||||
is returned. For large arrays of pointers with poor locality, it
|
||||
may be worthwhile to sort this array before calling bulk_free.
|
||||
*/
|
||||
size_t bulk_free(void**, size_t n_elements);
|
||||
|
||||
/*
|
||||
pvalloc(size_t n);
|
||||
Equivalent to valloc(minimum-page-that-holds(n)), that is,
|
||||
round up n to nearest pagesize.
|
||||
*/
|
||||
void* pvalloc(size_t);
|
||||
|
||||
/*
|
||||
malloc_trim(size_t pad);
|
||||
|
||||
If possible, gives memory back to the system (via negative arguments
|
||||
to sbrk) if there is unused memory at the `high' end of the malloc
|
||||
pool or in unused MMAP segments. You can call this after freeing
|
||||
large blocks of memory to potentially reduce the system-level memory
|
||||
requirements of a program. However, it cannot guarantee to reduce
|
||||
memory. Under some allocation patterns, some large free blocks of
|
||||
memory will be locked between two used chunks, so they cannot be
|
||||
given back to the system.
|
||||
|
||||
The `pad' argument to malloc_trim represents the amount of free
|
||||
trailing space to leave untrimmed. If this argument is zero, only
|
||||
the minimum amount of memory to maintain internal data structures
|
||||
will be left. Non-zero arguments can be supplied to maintain enough
|
||||
trailing space to service future expected allocations without having
|
||||
to re-obtain memory from the system.
|
||||
|
||||
Malloc_trim returns 1 if it actually released any memory, else 0.
|
||||
*/
|
||||
int malloc_trim(size_t);
|
||||
|
||||
/*
|
||||
malloc_stats();
|
||||
Prints on stderr the amount of space obtained from the system (both
|
||||
via sbrk and mmap), the maximum amount (which may be more than
|
||||
current if malloc_trim and/or munmap got called), and the current
|
||||
number of bytes allocated via malloc (or realloc, etc) but not yet
|
||||
freed. Note that this is the number of bytes allocated, not the
|
||||
number requested. It will be larger than the number requested
|
||||
because of alignment and bookkeeping overhead. Because it includes
|
||||
alignment wastage as being in use, this figure may be greater than
|
||||
zero even when no user-level chunks are allocated.
|
||||
|
||||
The reported current and maximum system memory can be inaccurate if
|
||||
a program makes other calls to system memory allocation functions
|
||||
(normally sbrk) outside of malloc.
|
||||
|
||||
malloc_stats prints only the most commonly interesting statistics.
|
||||
More information can be obtained by calling mallinfo.
|
||||
|
||||
malloc_stats is not compiled if NO_MALLOC_STATS is defined.
|
||||
*/
|
||||
void malloc_stats(void);
|
||||
|
||||
#endif /* !ONLY_MSPACES */
|
||||
|
||||
/*
|
||||
malloc_usable_size(void* p);
|
||||
|
||||
Returns the number of bytes you can actually use in
|
||||
an allocated chunk, which may be more than you requested (although
|
||||
often not) due to alignment and minimum size constraints.
|
||||
You can use this many bytes without worrying about
|
||||
overwriting other allocated objects. This is not a particularly great
|
||||
programming practice. malloc_usable_size can be more useful in
|
||||
debugging and assertions, for example:
|
||||
|
||||
p = malloc(n);
|
||||
assert(malloc_usable_size(p) >= 256);
|
||||
*/
|
||||
size_t malloc_usable_size(const void*);
|
||||
|
||||
#if MSPACES
|
||||
|
||||
/*
|
||||
mspace is an opaque type representing an independent
|
||||
region of space that supports mspace_malloc, etc.
|
||||
*/
|
||||
typedef void* mspace;
|
||||
|
||||
/*
|
||||
create_mspace creates and returns a new independent space with the
|
||||
given initial capacity, or, if 0, the default granularity size. It
|
||||
returns null if there is no system memory available to create the
|
||||
space. If argument locked is non-zero, the space uses a separate
|
||||
lock to control access. The capacity of the space will grow
|
||||
dynamically as needed to service mspace_malloc requests. You can
|
||||
control the sizes of incremental increases of this space by
|
||||
compiling with a different DEFAULT_GRANULARITY or dynamically
|
||||
setting with mallopt(M_GRANULARITY, value).
|
||||
*/
|
||||
mspace create_mspace(size_t capacity, int locked);
|
||||
|
||||
/*
|
||||
destroy_mspace destroys the given space, and attempts to return all
|
||||
of its memory back to the system, returning the total number of
|
||||
bytes freed. After destruction, the results of access to all memory
|
||||
used by the space become undefined.
|
||||
*/
|
||||
size_t destroy_mspace(mspace msp);
|
||||
|
||||
/*
|
||||
create_mspace_with_base uses the memory supplied as the initial base
|
||||
of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
|
||||
space is used for bookkeeping, so the capacity must be at least this
|
||||
large. (Otherwise 0 is returned.) When this initial space is
|
||||
exhausted, additional memory will be obtained from the system.
|
||||
Destroying this space will deallocate all additionally allocated
|
||||
space (if possible) but not the initial base.
|
||||
*/
|
||||
mspace create_mspace_with_base(void* base, size_t capacity, int locked);
|
||||
|
||||
/*
|
||||
mspace_track_large_chunks controls whether requests for large chunks
|
||||
are allocated in their own untracked mmapped regions, separate from
|
||||
others in this mspace. By default large chunks are not tracked,
|
||||
which reduces fragmentation. However, such chunks are not
|
||||
necessarily released to the system upon destroy_mspace. Enabling
|
||||
tracking by setting to true may increase fragmentation, but avoids
|
||||
leakage when relying on destroy_mspace to release all memory
|
||||
allocated using this space. The function returns the previous
|
||||
setting.
|
||||
*/
|
||||
int mspace_track_large_chunks(mspace msp, int enable);
|
||||
|
||||
#if !NO_MALLINFO
|
||||
/*
|
||||
mspace_mallinfo behaves as mallinfo, but reports properties of
|
||||
the given space.
|
||||
*/
|
||||
struct mallinfo mspace_mallinfo(mspace msp);
|
||||
#endif /* NO_MALLINFO */
|
||||
|
||||
/*
|
||||
An alias for mallopt.
|
||||
*/
|
||||
int mspace_mallopt(int, int);
|
||||
|
||||
/*
|
||||
The following operate identically to their malloc counterparts
|
||||
but operate only for the given mspace argument
|
||||
*/
|
||||
void* mspace_malloc(mspace msp, size_t bytes);
|
||||
void mspace_free(mspace msp, void* mem);
|
||||
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
|
||||
void* mspace_realloc(mspace msp, void* mem, size_t newsize);
|
||||
void* mspace_realloc_in_place(mspace msp, void* mem, size_t newsize);
|
||||
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
|
||||
void** mspace_independent_calloc(mspace msp, size_t n_elements, size_t elem_size, void* chunks[]);
|
||||
void** mspace_independent_comalloc(mspace msp, size_t n_elements, size_t sizes[], void* chunks[]);
|
||||
size_t mspace_bulk_free(mspace msp, void**, size_t n_elements);
|
||||
size_t mspace_usable_size(const void* mem);
|
||||
void mspace_malloc_stats(mspace msp);
|
||||
int mspace_trim(mspace msp, size_t pad);
|
||||
size_t mspace_footprint(mspace msp);
|
||||
size_t mspace_max_footprint(mspace msp);
|
||||
size_t mspace_footprint_limit(mspace msp);
|
||||
size_t mspace_set_footprint_limit(mspace msp, size_t bytes);
|
||||
void mspace_inspect_all(mspace msp, void (*handler)(void*, void*, size_t, void*), void* arg);
|
||||
#endif /* MSPACES */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}; /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* MALLOC_280_H */
|
13
libc/include/string.h
Normal file
13
libc/include/string.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef _STRING_H
|
||||
#define _STRING_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
int memcmp(const void*, const void*, size_t);
|
||||
void* memcpy(void* __restrict, const void* __restrict, size_t);
|
||||
void* memmove(void*, const void*, size_t);
|
||||
void* memset(void*, int, size_t);
|
||||
size_t strlen(const char*);
|
||||
|
||||
#endif
|
5
libc/include/sys/cdefs.h
Executable file
5
libc/include/sys/cdefs.h
Executable file
|
@ -0,0 +1,5 @@
|
|||
#ifndef _SYS_CDEFS_H
|
||||
#define _SYS_CDEFS_H 1
|
||||
|
||||
#define __red_libc 1
|
||||
#endif
|
0
libc/include/sys/types.h
Executable file
0
libc/include/sys/types.h
Executable file
93
libc/stdio/printf.c
Normal file
93
libc/stdio/printf.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static bool print(const char* data, size_t length) {
|
||||
const unsigned char* bytes = (const unsigned char*)data;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
if (putchar(bytes[i]) == EOF)
|
||||
return false' return true;
|
||||
}
|
||||
|
||||
int printf(const char* restrict format, ...) {
|
||||
va_list parameters;
|
||||
va_start(parameters, format);
|
||||
|
||||
int written = 0;
|
||||
|
||||
while (*format != '\0') {
|
||||
size_t maxrem = INT_MAX - writen;
|
||||
|
||||
if (format[0] != '%' || format[1] == '%') {
|
||||
if (format[0] == '%')
|
||||
format++;
|
||||
size_t amount = 1;
|
||||
|
||||
while (format[amount] && format[amount] != '%')
|
||||
amount++;
|
||||
|
||||
if (maxrem < amount) {
|
||||
// TODO: Set an OVERFLOW error
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((!print(format, amount))
|
||||
return -1;
|
||||
|
||||
format += amount;
|
||||
written += amount;
|
||||
continue;
|
||||
}
|
||||
|
||||
const char* first_format = format++;
|
||||
|
||||
switch (*format) {
|
||||
case 'c':
|
||||
format++;
|
||||
char c = (char)va_arg(parameters, int);
|
||||
if (!maxrem) {
|
||||
// TODO: Set OVERFLOW
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!print(&c, sizeof(c)))
|
||||
return -1;
|
||||
written++;
|
||||
break;
|
||||
case 's':
|
||||
format++;
|
||||
|
||||
const char* str = va_arg(parameters, const char*);
|
||||
size_t len = strlen(str);
|
||||
|
||||
if (maxrem < len) {
|
||||
// TODO: Set OVERFLOW
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!print(str, len))
|
||||
return -1;
|
||||
|
||||
written += len;
|
||||
break;
|
||||
default:
|
||||
format = first_format;
|
||||
size_t len = strlen(format);
|
||||
if (maxrem < len) {
|
||||
// TODO: Set OVERFLOW
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!print(format, len))
|
||||
return -1;
|
||||
written += len;
|
||||
format += len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(parameters);
|
||||
return written;
|
||||
}
|
15
libc/stdio/putchar.c
Normal file
15
libc/stdio/putchar.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#if defined(__is_libk)
|
||||
#include <kernel/tty.h>
|
||||
#endif
|
||||
|
||||
int putchar(int ic) {
|
||||
#if defined(__is_libk)
|
||||
char c = (char)ic;
|
||||
term_write(&c, sizeof(c));
|
||||
#else
|
||||
// TODO: Implement stdio & the write call
|
||||
#endif
|
||||
return ic;
|
||||
}
|
5
libc/stdio/puts.c
Executable file
5
libc/stdio/puts.c
Executable file
|
@ -0,0 +1,5 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int puts(const char* string) {
|
||||
return printf("%s\n"), string);
|
||||
}
|
15
libc/stdlib/abort.c
Normal file
15
libc/stdlib/abort.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
__attribute__((__noreturn__)) void abort(void) {
|
||||
|
||||
#if defined(__is_libk)
|
||||
// TODO: Kernel panic.
|
||||
printf(">>PANIC<<<\n abort() panicked!\n");
|
||||
#else
|
||||
printf("abort() called\n");
|
||||
#endif
|
||||
while (1) {
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
13
libc/string/memcmp.c
Normal file
13
libc/string/memcmp.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include <string.h>
|
||||
|
||||
int memcmp(const void* aptr, const void* bptr, size_t size_ {
|
||||
const unsigned char* a = (const unsigned char*)aptr;
|
||||
const unsigned char* b = (const unsigned char*)bptr;
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if(a[i] < b[i]
|
||||
return -1
|
||||
else if(b[i] < a[i])
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
14
libc/string/memmove.c
Normal file
14
libc/string/memmove.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <string.h>
|
||||
|
||||
void* memmove(void* dstptr, const void* srcptr, size_t size) {
|
||||
unsigned char* dst = (unsigned char*)dstptr;
|
||||
const unsigned char* stc = (const unsigned char*)srcptr;
|
||||
if (dst < src) {
|
||||
for (size_t i = o; i < size; i++)
|
||||
dst[i] = src[i];
|
||||
} else {
|
||||
for (size_t i = size; i != 0; i--)
|
||||
dst[i - 1] = src[i - 1];
|
||||
}
|
||||
return dstptr;
|
||||
}
|
8
libc/string/memset.c
Normal file
8
libc/string/memset.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <string.h>
|
||||
|
||||
void* memset(void* bufptr, int value, size_t size) {
|
||||
unsigned char* buf = (unsigned char*)bufptr;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buf[i] = (unsigned char)value;
|
||||
return bufptr;
|
||||
}
|
7
libc/string/strlen.c
Normal file
7
libc/string/strlen.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include <string.h>
|
||||
|
||||
size_t strlen(const char* str) {
|
||||
size_t len = 0;
|
||||
while (str[len])
|
||||
len++ return len;
|
||||
}
|
BIN
red.kernel
Executable file
BIN
red.kernel
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user