mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
add basic bootloader to support a non multi-kernel mode
=> HermitCore will support a classical unikernel mode
This commit is contained in:
parent
5782edd4eb
commit
66195c7795
18 changed files with 2581 additions and 0 deletions
66
hermit/arch/x86/loader/Makefile
Normal file
66
hermit/arch/x86/loader/Makefile
Normal file
|
@ -0,0 +1,66 @@
|
|||
MAKE = make
|
||||
QEMU = qemu-system-x86_64 -machine accel=kvm -cpu host
|
||||
OBJDUMP = objdump
|
||||
OBJCOPY = objcopy
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -Wall -m64 -ffreestanding -mno-red-zone -fstrength-reduce -fomit-frame-pointer -finline-functions -Iinclude
|
||||
NASM = nasm
|
||||
NASMFLAGS = -felf64 -g
|
||||
LD = ld
|
||||
LDFLAGS = -T link.ld -z max-page-size=4096
|
||||
STRIP_DEBUG = --strip-debug
|
||||
KEEP_DEBUG = --only-keep-debug
|
||||
OUTPUT_FORMAT = -O elf32-i386
|
||||
NAME = ldhermit
|
||||
|
||||
C_source := main.c printf.c string.c stdio.c vga.c page.c
|
||||
ASM_source := entry.asm
|
||||
|
||||
OBJS := $(C_source:.c=.o)
|
||||
OBJS += $(ASM_source:.asm=.o)
|
||||
|
||||
# Prettify output
|
||||
V = 0
|
||||
ifeq ($V,0)
|
||||
Q = @
|
||||
P = > /dev/null
|
||||
endif
|
||||
|
||||
# other implicit rules
|
||||
%.o : %.c
|
||||
@echo [CC] $@
|
||||
$Q$(CC) -c $(CFLAGS) -o $@ $<
|
||||
@echo [DEP] $*.dep
|
||||
$Q$(CC) -MF $*.dep -MT $*.o -MM $(CFLAGS) $<
|
||||
|
||||
%.o : %.asm
|
||||
@echo [ASM] $@
|
||||
$Q$(NASM) $(NASMFLAGS) -o $@ $<
|
||||
|
||||
all: ldhermit.elf
|
||||
|
||||
$(NAME).elf: $(OBJS)
|
||||
@echo [LD] $@
|
||||
$Q$(LD) $(LDFLAGS) -o $@ $(OBJS)
|
||||
@echo [OBJCOPY] $(NAME).sym
|
||||
$Q$(OBJCOPY) $(KEEP_DEBUG) $(NAME).elf $(NAME).sym
|
||||
@echo [OBJCOPY] $(NAME).elf
|
||||
$Q$(OBJCOPY) $(STRIP_DEBUG) $(OUTPUT_FORMAT) $(NAME).elf
|
||||
|
||||
qemu:
|
||||
$(QEMU) -smp 10 -m 4G -kernel $(NAME).elf -initrd ../../../usr/tests/hello \
|
||||
-net nic,model=rtl8139 -net user -net dump \
|
||||
-curses -monitor telnet:127.0.0.1:1235,server,nowait \
|
||||
-s
|
||||
|
||||
clean:
|
||||
@echo Cleaning loader
|
||||
$Q$(RM) -rf *.o *~ *.bin *.obj
|
||||
|
||||
veryclean: clean
|
||||
|
||||
depend:
|
||||
$(CC) -MM $(CFLAGS) *.c > Makefile.dep
|
||||
|
||||
-include -include $(C_source:.c=.dep)
|
||||
# DO NOT DELETE
|
289
hermit/arch/x86/loader/entry.asm
Normal file
289
hermit/arch/x86/loader/entry.asm
Normal file
|
@ -0,0 +1,289 @@
|
|||
|
||||
; Copyright (c) 2010-2016, Stefan Lankes, RWTH Aachen University
|
||||
; All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions are met:
|
||||
; * Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; * Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in the
|
||||
; documentation and/or other materials provided with the distribution.
|
||||
; * Neither the name of the University nor the names of its contributors
|
||||
; may be used to endorse or promote products derived from this software
|
||||
; without specific prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
; DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
; This is the kernel's entry point. We could either call main here,
|
||||
; or we can use this to setup the stack or other nice stuff, like
|
||||
; perhaps setting up the GDT and segments. Please note that interrupts
|
||||
; are disabled at this point: More on interrupts later!
|
||||
|
||||
[BITS 32]
|
||||
|
||||
%define KERNEL_STACK_SIZE 4096
|
||||
%define VIDEO_MEM_ADDR 0xB8000
|
||||
|
||||
extern kernel_start ; defined in linker script
|
||||
extern kernel_end
|
||||
|
||||
; We use a special name to map this section at the begin of our kernel
|
||||
; => Multiboot expects its magic number at the beginning of the kernel.
|
||||
SECTION .mboot
|
||||
global start
|
||||
start:
|
||||
jmp stublet
|
||||
|
||||
; This part MUST be 4 byte aligned, so we solve that issue using 'ALIGN 4'.
|
||||
ALIGN 4
|
||||
mboot:
|
||||
; Multiboot macros to make a few lines more readable later
|
||||
MULTIBOOT_PAGE_ALIGN equ (1 << 0)
|
||||
MULTIBOOT_MEMORY_INFO equ (1 << 1)
|
||||
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
|
||||
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
|
||||
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
||||
|
||||
; This is the GRUB Multiboot header. A boot signature
|
||||
dd MULTIBOOT_HEADER_MAGIC
|
||||
dd MULTIBOOT_HEADER_FLAGS
|
||||
dd MULTIBOOT_CHECKSUM
|
||||
dd 0, 0, 0, 0, 0 ; address fields
|
||||
|
||||
ALIGN 4
|
||||
; we need already a valid GDT to switch in the 64bit modus
|
||||
GDT64: ; Global Descriptor Table (64-bit).
|
||||
.Null: equ $ - GDT64 ; The null descriptor.
|
||||
dw 0 ; Limit (low).
|
||||
dw 0 ; Base (low).
|
||||
db 0 ; Base (middle)
|
||||
db 0 ; Access.
|
||||
db 0 ; Granularity.
|
||||
db 0 ; Base (high).
|
||||
.Code: equ $ - GDT64 ; The code descriptor.
|
||||
dw 0 ; Limit (low).
|
||||
dw 0 ; Base (low).
|
||||
db 0 ; Base (middle)
|
||||
db 10011000b ; Access.
|
||||
db 00100000b ; Granularity.
|
||||
db 0 ; Base (high).
|
||||
.Data: equ $ - GDT64 ; The data descriptor.
|
||||
dw 0 ; Limit (low).
|
||||
dw 0 ; Base (low).
|
||||
db 0 ; Base (middle)
|
||||
db 10010010b ; Access.
|
||||
db 00000000b ; Granularity.
|
||||
db 0 ; Base (high).
|
||||
.Pointer: ; The GDT-pointer.
|
||||
dw $ - GDT64 - 1 ; Limit.
|
||||
dq GDT64 ; Base.
|
||||
|
||||
SECTION .text
|
||||
ALIGN 4
|
||||
stublet:
|
||||
; Initialize stack pointer
|
||||
mov esp, boot_stack
|
||||
add esp, KERNEL_STACK_SIZE - 16
|
||||
|
||||
; Interpret multiboot information
|
||||
mov DWORD [mb_info], ebx
|
||||
|
||||
; Initialize CPU features
|
||||
call cpu_init
|
||||
|
||||
pop ebx ; restore pointer to multiboot structure
|
||||
lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table.
|
||||
jmp GDT64.Code:start64 ; Set the code segment and enter 64-bit long mode.
|
||||
|
||||
; This will set up the x86 control registers:
|
||||
; Caching and the floating point unit are enabled
|
||||
; Bootstrap page tables are loaded and page size
|
||||
; extensions (huge pages) enabled.
|
||||
global cpu_init
|
||||
cpu_init:
|
||||
|
||||
; initialize page tables
|
||||
|
||||
; map vga 1:1
|
||||
push edi
|
||||
mov eax, VIDEO_MEM_ADDR ; map vga
|
||||
and eax, 0xFFFFF000 ; page align lower half
|
||||
mov edi, eax
|
||||
shr edi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
|
||||
add edi, boot_pgt
|
||||
or eax, 0x113 ; set present, global, writable and cache disable bits
|
||||
mov DWORD [edi], eax
|
||||
pop edi
|
||||
|
||||
; map multiboot info 1:1
|
||||
push edi
|
||||
mov eax, DWORD [mb_info] ; map multiboot info
|
||||
and eax, 0xFFFFF000 ; page align lower half
|
||||
mov edi, eax
|
||||
shr edi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
|
||||
add edi, boot_pgt
|
||||
or eax, 0x101 ; set present and global bits
|
||||
mov DWORD [edi], eax
|
||||
pop edi
|
||||
|
||||
; map kernel 1:1
|
||||
push edi
|
||||
push ebx
|
||||
push ecx
|
||||
mov ecx, kernel_start
|
||||
mov ebx, kernel_end
|
||||
add ebx, 0x1000
|
||||
L0: cmp ecx, ebx
|
||||
jae L1
|
||||
mov eax, ecx
|
||||
and eax, 0xFFFFF000 ; page align lower half
|
||||
mov edi, eax
|
||||
shr edi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
|
||||
add edi, boot_pgt
|
||||
or eax, 0x103 ; set present, global and writable bits
|
||||
mov DWORD [edi], eax
|
||||
add ecx, 0x1000
|
||||
jmp L0
|
||||
L1:
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop edi
|
||||
|
||||
; check for long mode
|
||||
|
||||
; do we have the instruction cpuid?
|
||||
pushfd
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 1 << 21
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
push ecx
|
||||
popfd
|
||||
xor eax, ecx
|
||||
jz Linvalid
|
||||
|
||||
; cpuid > 0x80000000?
|
||||
mov eax, 0x80000000
|
||||
cpuid
|
||||
cmp eax, 0x80000001
|
||||
jb Linvalid ; It is less, there is no long mode.
|
||||
|
||||
; do we have a long mode?
|
||||
mov eax, 0x80000001
|
||||
cpuid
|
||||
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
|
||||
jz Linvalid ; They aren't, there is no long mode.
|
||||
|
||||
|
||||
; we need to enable PAE modus
|
||||
mov eax, cr4
|
||||
or eax, 1 << 5
|
||||
mov cr4, eax
|
||||
|
||||
; switch to the compatibility mode (which is part of long mode)
|
||||
mov ecx, 0xC0000080
|
||||
rdmsr
|
||||
or eax, 1 << 8
|
||||
wrmsr
|
||||
|
||||
; Set CR3
|
||||
mov eax, boot_pml4
|
||||
mov cr3, eax
|
||||
|
||||
; Set CR4
|
||||
mov eax, cr4
|
||||
and eax, 0xfffbf9ff ; disable SSE
|
||||
or eax, (1 << 4) ; enable PSE
|
||||
or eax, (1 << 7) ; enabel PGE
|
||||
mov cr4, eax
|
||||
|
||||
; Set CR0
|
||||
mov eax, cr0
|
||||
and eax, ~(1 << 2) ; disable FPU emulation
|
||||
or eax, (1 << 1) ; enable FPU montitoring
|
||||
and eax, ~(1 << 30) ; enable caching
|
||||
and eax, ~(1 << 29) ; disable write through caching
|
||||
and eax, ~(1 << 16) ; allow kernel write access to read-only pages
|
||||
or eax, (1 << 31) ; enable paging
|
||||
or eax, (1 << 0) ; long mode also needs PM-bit set
|
||||
mov cr0, eax
|
||||
|
||||
ret
|
||||
|
||||
; there is no long mode
|
||||
Linvalid:
|
||||
jmp $
|
||||
|
||||
|
||||
[BITS 64]
|
||||
start64:
|
||||
; initialize segment registers
|
||||
mov ax, GDT64.Data
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov ss, ax
|
||||
mov ax, 0x00
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
; set default stack pointer
|
||||
mov rsp, boot_stack
|
||||
add rsp, KERNEL_STACK_SIZE-16
|
||||
|
||||
; jump to the boot processors's C code
|
||||
extern main
|
||||
call main
|
||||
jmp $
|
||||
|
||||
;global gdt_flush
|
||||
;extern gp
|
||||
|
||||
; This will set up our new segment registers and is declared in
|
||||
; C as 'extern void gdt_flush();'
|
||||
;gdt_flush:
|
||||
; lgdt [gp]
|
||||
; ret
|
||||
|
||||
SECTION .data
|
||||
|
||||
global mb_info:
|
||||
ALIGN 8
|
||||
mb_info:
|
||||
DQ 0
|
||||
|
||||
ALIGN 4096
|
||||
global boot_stack
|
||||
boot_stack:
|
||||
TIMES (KERNEL_STACK_SIZE) DB 0xcd
|
||||
|
||||
; Bootstrap page tables are used during the initialization.
|
||||
ALIGN 4096
|
||||
boot_pml4:
|
||||
DQ boot_pdpt + 0x107 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
|
||||
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
||||
DQ boot_pml4 + 0x303 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_SELF (self-reference)
|
||||
boot_pdpt:
|
||||
DQ boot_pgd + 0x107 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
|
||||
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
||||
DQ boot_pml4 + 0x303 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_SELF (self-reference)
|
||||
boot_pgd:
|
||||
DQ boot_pgt + 0x107 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_USER
|
||||
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
||||
DQ boot_pml4 + 0x303 ; PG_PRESENT | PG_GLOBAL | PG_RW | PG_SELF (self-reference)
|
||||
boot_pgt:
|
||||
times 512 DQ 0
|
||||
|
||||
; add some hints to the ELF file
|
||||
SECTION .note.GNU-stack noalloc noexec nowrite progbits
|
177
hermit/arch/x86/loader/include/elf.h
Normal file
177
hermit/arch/x86/loader/include/elf.h
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* This file keeps define constants for identification and definition of ELF files.\n
|
||||
* ELF files consist of up to five parts:
|
||||
* - ELF header
|
||||
* - program header table
|
||||
* - section header table
|
||||
* - ELF sections
|
||||
* - ELF segment
|
||||
*/
|
||||
#ifndef __ELF_H__
|
||||
#define __ELF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ELF_MAGIC 0x464C457F
|
||||
|
||||
#define ELF_ET_NONE 0x0000 // no type
|
||||
#define ELF_ET_REL 0x0001 // relocatable
|
||||
#define ELF_ET_EXEC 0x0002 // executeable
|
||||
#define ELF_ET_DYN 0x0003 // Shared-Object-File
|
||||
#define ELF_ET_CORE 0x0004 // Corefile
|
||||
#define ELF_ET_LOPROC 0xFF00 // Processor-specific
|
||||
#define ELF_ET_HIPROC 0x00FF // Processor-specific
|
||||
|
||||
#define ELF_EM_NONE 0x0000 // no type
|
||||
#define ELF_EM_M32 0x0001 // AT&T WE 32100
|
||||
#define ELF_EM_SPARC 0x0002 // SPARC
|
||||
#define ELF_EM_386 0x0003 // Intel 80386
|
||||
#define ELF_EM_68K 0x0004 // Motorola 68000
|
||||
#define ELF_EM_88K 0x0005 // Motorola 88000
|
||||
#define ELF_EM_860 0x0007 // Intel 80860
|
||||
#define ELF_EM_MIPS 0x0008 // MIPS RS3000
|
||||
#define ELF_EM_X86_64 0x003e // Intel X86_64
|
||||
|
||||
#define ELF_CLASS_NONE 0x0000
|
||||
#define ELF_CLASS_32 0x0001 // 32bit file
|
||||
#define ELF_CLASS_64 0x0002 // 64bit file
|
||||
|
||||
#define ELF_DATA_NONE 0x0000
|
||||
#define ELF_DATA_2LSB 0x0001
|
||||
#define ELF_DATA_2MSB 0x002
|
||||
|
||||
/* Legal values for p_type (segment type). */
|
||||
|
||||
#define ELF_PT_NULL 0 /* Program header table entry unused */
|
||||
#define ELF_PT_LOAD 1 /* Loadable program segment */
|
||||
#define ELF_PT_DYNAMIC 2 /* Dynamic linking information */
|
||||
#define ELF_PT_INTERP 3 /* Program interpreter */
|
||||
#define ELF_PT_NOTE 4 /* Auxiliary information */
|
||||
#define ELF_PT_SHLIB 5
|
||||
#define ELF_PT_PHDR 6 /* Entry for header table itself */
|
||||
#define ELF_PT_TLS 7 /* Thread-local storage segment */
|
||||
#define ELF_PT_NUM 8 /* Number of defined types */
|
||||
#define ELF_PT_LOOS 0x60000000 /* Start of OS-specific */
|
||||
#define ELF_PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
|
||||
#define ELF_PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
|
||||
#define ELF_PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
|
||||
#define ELF_PT_LOSUNW 0x6ffffffa
|
||||
#define ELF_PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
|
||||
#define ELF_PT_SUNWSTACK 0x6ffffffb /* Stack segment */
|
||||
#define ELF_PT_HISUNW 0x6fffffff
|
||||
#define ELF_PT_HIOS 0x6fffffff /* End of OS-specific */
|
||||
#define ELF_PT_LOPROC 0x70000000 /* Start of processor-specific */
|
||||
#define ELF_PT_HIPROC 0x7fffffff /* End of processor-specific */
|
||||
|
||||
/* These constants define the permissions on sections in the program
|
||||
header, p_flags. */
|
||||
#define PF_R 0x4
|
||||
#define PF_W 0x2
|
||||
#define PF_X 0x1
|
||||
|
||||
/** @brief Identification part of an ELF-file's header
|
||||
*
|
||||
* This structure keeps information about the file format
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint8_t _class;
|
||||
uint8_t data;
|
||||
uint8_t version;
|
||||
uint8_t pad[8];
|
||||
uint8_t nident;
|
||||
} __attribute__ ((packed)) elf_ident_t;
|
||||
|
||||
/** @brief Information about the executable
|
||||
*
|
||||
* ELF header\n
|
||||
* This structure keeps information about the format of the executable itself.
|
||||
*/
|
||||
typedef struct {
|
||||
elf_ident_t ident;
|
||||
uint16_t type;
|
||||
uint16_t machine;
|
||||
uint32_t version;
|
||||
size_t entry;
|
||||
size_t ph_offset;
|
||||
size_t sh_offset;
|
||||
uint32_t flags;
|
||||
uint16_t header_size;
|
||||
uint16_t ph_entry_size;
|
||||
uint16_t ph_entry_count;
|
||||
uint16_t sh_entry_size;
|
||||
uint16_t sh_entry_count;
|
||||
uint16_t sh_str_table_index;
|
||||
} __attribute__ ((packed)) elf_header_t;
|
||||
|
||||
/** @brief program header information
|
||||
*
|
||||
* program header table\n
|
||||
* This structure keeps information about the program header.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t type;
|
||||
uint32_t flags;
|
||||
uint64_t offset;
|
||||
uint64_t virt_addr;
|
||||
uint64_t phys_addr;
|
||||
uint64_t file_size;
|
||||
uint64_t mem_size;
|
||||
uint64_t alignment;
|
||||
} __attribute__ ((packed)) elf_program_header_t;
|
||||
|
||||
/** @brief Information about ELF section
|
||||
*
|
||||
* ELF section\n
|
||||
* This structure keeps information about a specific ELF section
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t name;
|
||||
uint32_t type;
|
||||
uint64_t flags;
|
||||
uint64_t addr;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
uint32_t link;
|
||||
uint32_t info;
|
||||
uint64_t align;
|
||||
uint64_t enttry_size;
|
||||
} __attribute__ ((packed)) elf_section_header_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
100
hermit/arch/x86/loader/include/io.h
Normal file
100
hermit/arch/x86/loader/include/io.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __IO_H__
|
||||
#define __IO_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Read a byte from an IO port
|
||||
*
|
||||
* @param _port The port you want to read from
|
||||
* @return The value which reads out from this port
|
||||
*/
|
||||
inline static unsigned char inportb(unsigned short _port) {
|
||||
unsigned char rv;
|
||||
asm volatile("inb %1, %0":"=a"(rv):"dN"(_port));
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** @brief Read a word (2 byte) from an IO port
|
||||
*
|
||||
* @param _port The port you want to read from
|
||||
* @return The value which reads out from this port
|
||||
*/
|
||||
inline static unsigned short inportw(unsigned short _port) {
|
||||
unsigned short rv;
|
||||
asm volatile("inw %1, %0":"=a"(rv):"dN"(_port));
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** @brief Read a double word (4 byte) from an IO port
|
||||
*
|
||||
* @param _port The port you want to read from
|
||||
* @return The value which reads out from this port
|
||||
*/
|
||||
inline static unsigned int inportl(unsigned short _port) {
|
||||
unsigned int rv;
|
||||
asm volatile("inl %1, %0":"=a"(rv):"dN"(_port));
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** @brief Write a byte to an IO port
|
||||
*
|
||||
* @param _port The port you want to write to
|
||||
* @param _data the 1 byte value you want to write
|
||||
*/
|
||||
inline static void outportb(unsigned short _port, unsigned char _data) {
|
||||
asm volatile("outb %1, %0"::"dN"(_port), "a"(_data));
|
||||
}
|
||||
|
||||
/** @brief Write a word (2 bytes) to an IO port
|
||||
*
|
||||
* @param _port The port you want to write to
|
||||
* @param _data the 2 byte value you want to write
|
||||
*/
|
||||
inline static void outportw(unsigned short _port, unsigned short _data) {
|
||||
asm volatile("outw %1, %0"::"dN"(_port), "a"(_data));
|
||||
}
|
||||
|
||||
/** @brief Write a double word (4 bytes) to an IO port
|
||||
*
|
||||
* @param _port The port you want to write to
|
||||
* @param _data the 4 byte value you want to write
|
||||
*/
|
||||
inline static void outportl(unsigned short _port, unsigned int _data)
|
||||
{
|
||||
asm volatile("outl %1, %0"::"dN"(_port), "a"(_data));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
148
hermit/arch/x86/loader/include/multiboot.h
Normal file
148
hermit/arch/x86/loader/include/multiboot.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_MULTIBOOT_H__
|
||||
#define __ARCH_MULTIBOOT_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/// Does the bootloader provide mem_* fields?
|
||||
#define MULTIBOOT_INFO_MEM (1 << 0)
|
||||
/// Does the bootloader provide the command-line?
|
||||
#define MULTIBOOT_INFO_CMDLINE (1 << 2)
|
||||
/// Does the bootloader provide a list of modules?
|
||||
#define MULTIBOOT_INFO_MODS (1 << 3)
|
||||
/// Does the bootloader provide a full memory map?
|
||||
#define MULTIBOOT_INFO_MEM_MAP (1 << 6)
|
||||
|
||||
typedef uint16_t multiboot_uint16_t;
|
||||
typedef uint32_t multiboot_uint32_t;
|
||||
typedef uint64_t multiboot_uint64_t;
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
typedef struct multiboot_info multiboot_info_t;
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
/// Pointer to multiboot structure
|
||||
/// This pointer is declared at set by entry.asm
|
||||
extern multiboot_info_t* mb_info;
|
||||
|
||||
#endif
|
164
hermit/arch/x86/loader/include/page.h
Normal file
164
hermit/arch/x86/loader/include/page.h
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* 2014, Steffen Vogel, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef __PAGE_H__
|
||||
#define __PAGE_H__
|
||||
|
||||
/// Page offset bits
|
||||
#define PAGE_BITS 12
|
||||
/// The size of a single page in bytes
|
||||
#define PAGE_SIZE ( 1L << PAGE_BITS)
|
||||
/// Mask the page address without page map flags and XD flag
|
||||
#ifdef CONFIG_X86_32
|
||||
#define PAGE_MASK (-1L << PAGE_BITS)
|
||||
#elif defined(CONFIG_X86_64)
|
||||
#define PAGE_MASK ((-1L << PAGE_BITS) & ~PG_XD)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/// Total operand width in bits
|
||||
#define BITS 32
|
||||
/// Physical address width (we dont support PAE)
|
||||
#define PHYS_BITS BITS
|
||||
/// Linear/virtual address width
|
||||
#define VIRT_BITS BITS
|
||||
/// Page map bits
|
||||
#define PAGE_MAP_BITS 10
|
||||
/// Number of page map indirections
|
||||
#define PAGE_LEVELS 2
|
||||
#elif defined(CONFIG_X86_64)
|
||||
/// Total operand width in bits
|
||||
#define BITS 64
|
||||
/// Physical address width (maximum value)
|
||||
#define PHYS_BITS 52
|
||||
/// Linear/virtual address width
|
||||
#define VIRT_BITS 48
|
||||
/// Page map bits
|
||||
#define PAGE_MAP_BITS 9
|
||||
/// Number of page map indirections
|
||||
#define PAGE_LEVELS 4
|
||||
|
||||
/** @brief Sign extending a integer
|
||||
*
|
||||
* @param addr The integer to extend
|
||||
* @param bits The width if addr which should be extended
|
||||
* @return The extended integer
|
||||
*/
|
||||
static inline size_t sign_extend(ssize_t addr, int bits)
|
||||
{
|
||||
int shift = BITS - bits;
|
||||
return (addr << shift) >> shift; // sign bit gets copied during arithmetic right shift
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Make address canonical
|
||||
#ifdef CONFIG_X86_32
|
||||
#define CANONICAL(addr) (addr) // only for 32 bit paging
|
||||
#elif defined(CONFIG_X86_64)
|
||||
#define CANONICAL(addr) sign_extend(addr, VIRT_BITS)
|
||||
#endif
|
||||
|
||||
/// The number of entries in a page map table
|
||||
#define PAGE_MAP_ENTRIES (1L << PAGE_MAP_BITS)
|
||||
|
||||
/// Align to next page
|
||||
#define PAGE_FLOOR(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
|
||||
/// Align to page
|
||||
#define PAGE_CEIL(addr) ( (addr) & PAGE_MASK)
|
||||
|
||||
/// Page is present
|
||||
#define PG_PRESENT (1 << 0)
|
||||
/// Page is read- and writable
|
||||
#define PG_RW (1 << 1)
|
||||
/// Page is addressable from userspace
|
||||
#define PG_USER (1 << 2)
|
||||
/// Page write through is activated
|
||||
#define PG_PWT (1 << 3)
|
||||
/// Page cache is disabled
|
||||
#define PG_PCD (1 << 4)
|
||||
/// Page was recently accessed (set by CPU)
|
||||
#define PG_ACCESSED (1 << 5)
|
||||
/// Page is dirty due to recent write-access (set by CPU)
|
||||
#define PG_DIRTY (1 << 6)
|
||||
/// Huge page: 4MB (or 2MB, 1GB)
|
||||
#define PG_PSE (1 << 7)
|
||||
/// Page attribute table
|
||||
#define PG_PAT PG_PSE
|
||||
/// Global TLB entry (Pentium Pro and later)
|
||||
#define PG_GLOBAL (1 << 8)
|
||||
/// This table is a self-reference and should skipped by page_map_copy()
|
||||
#define PG_SELF (1 << 9)
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
/// Disable execution for this page
|
||||
#define PG_XD (1L << 63)
|
||||
#endif
|
||||
|
||||
/** @brief Converts a virtual address to a physical
|
||||
*
|
||||
* A non mapped virtual address causes a pagefault!
|
||||
*
|
||||
* @param addr Virtual address to convert
|
||||
* @return physical address
|
||||
*/
|
||||
size_t virt_to_phys(size_t vir);
|
||||
|
||||
/** @brief Initialize paging subsystem
|
||||
*
|
||||
* This function uses the existing bootstrap page tables (boot_{pgd, pgt})
|
||||
* to map required regions (video memory, kernel, etc..).
|
||||
* Before calling page_init(), the bootstrap tables contain a simple identity
|
||||
* paging. Which is replaced by more specific mappings.
|
||||
*/
|
||||
int page_init(void);
|
||||
|
||||
/** @brief Map a continuous region of pages
|
||||
*
|
||||
* @param viraddr Desired virtual address
|
||||
* @param phyaddr Physical address to map from
|
||||
* @param npages The region's size in number of pages
|
||||
* @param bits Further page flags
|
||||
* @return
|
||||
*/
|
||||
int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits);
|
||||
|
||||
/** @brief Unmap a continuous region of pages
|
||||
*
|
||||
* @param viraddr The virtual start address
|
||||
* @param npages The range's size in pages
|
||||
* @return
|
||||
*/
|
||||
int page_unmap(size_t viraddr, size_t npages);
|
||||
|
||||
/** @brief Allocate a physical page frame
|
||||
*/
|
||||
size_t get_page(void);
|
||||
|
||||
#endif
|
50
hermit/arch/x86/loader/include/stdarg.h
Normal file
50
hermit/arch/x86/loader/include/stdarg.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __STDARG_H__
|
||||
#define __STDARG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef __builtin_va_list va_list;
|
||||
|
||||
/// Initialize a variable argument list
|
||||
#define va_start __builtin_va_start
|
||||
/// Retrieve next argument
|
||||
#define va_arg __builtin_va_arg
|
||||
/// End using variable argument list
|
||||
#define va_end __builtin_va_end
|
||||
/// copies the (previously initialized) variable argument list
|
||||
#define va_copy __builtin_va_copy
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
92
hermit/arch/x86/loader/include/stddef.h
Normal file
92
hermit/arch/x86/loader/include/stddef.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains typedefs for standard datatypes for numerical and character values.
|
||||
*/
|
||||
|
||||
#ifndef __STDDEF_H__
|
||||
#define __STDDEF_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NULL ((void*) 0)
|
||||
#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b))
|
||||
//#define BUILTIN_EXPECT(exp, b) (exp)
|
||||
|
||||
#if __SIZEOF_POINTER__ == 4
|
||||
|
||||
#define CONFIG_X86_32
|
||||
|
||||
/// This type is used to represent the size of an object.
|
||||
typedef unsigned long size_t;
|
||||
/// Pointer differences
|
||||
typedef long ptrdiff_t;
|
||||
/// It is similar to size_t, but must be a signed type.
|
||||
typedef long ssize_t;
|
||||
/// The type represents an offset and is similar to size_t, but must be a signed type.
|
||||
typedef long off_t;
|
||||
#elif __SIZEOF_POINTER__ == 8
|
||||
|
||||
#define CONFIG_X86_64
|
||||
|
||||
// A popular type for addresses
|
||||
typedef unsigned long long size_t;
|
||||
/// Pointer differences
|
||||
typedef long long ptrdiff_t;
|
||||
typedef long long ssize_t;
|
||||
typedef long long off_t;
|
||||
#else
|
||||
#error unsupported architecture
|
||||
#endif
|
||||
|
||||
/// Unsigned 64 bit integer
|
||||
typedef unsigned long long uint64_t;
|
||||
/// Signed 64 bit integer
|
||||
typedef long long int64_t;
|
||||
/// Unsigned 32 bit integer
|
||||
typedef unsigned int uint32_t;
|
||||
/// Signed 32 bit integer
|
||||
typedef int int32_t;
|
||||
/// Unsigned 16 bit integer
|
||||
typedef unsigned short uint16_t;
|
||||
/// Signed 16 bit integer
|
||||
typedef short int16_t;
|
||||
/// Unsigned 8 bit integer (/char)
|
||||
typedef unsigned char uint8_t;
|
||||
/// Signed 8 bit integer (/char)
|
||||
typedef char int8_t;
|
||||
/// 16 bit wide char type
|
||||
typedef unsigned short wchar_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
77
hermit/arch/x86/loader/include/stdio.h
Normal file
77
hermit/arch/x86/loader/include/stdio.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __STDIO_H__
|
||||
#define __STDIO_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Works like the ANSI C function puts
|
||||
*/
|
||||
int kputs(const char *);
|
||||
|
||||
/**
|
||||
* Works like the ANSI C function putchar
|
||||
*/
|
||||
int kputchar(int);
|
||||
|
||||
/**
|
||||
* Works like the ANSI C function printf
|
||||
*/
|
||||
int kprintf(const char*, ...);
|
||||
|
||||
/**
|
||||
* Initialize the I/O functions
|
||||
*/
|
||||
int koutput_init(void);
|
||||
|
||||
/**
|
||||
* Works like the ANSI c function sprintf
|
||||
*/
|
||||
int ksprintf(char *str, const char *format, ...);
|
||||
|
||||
/**
|
||||
* Works like the ANSI c function sprintf
|
||||
*/
|
||||
int ksnprintf(char *str, size_t size, const char *format, ...);
|
||||
|
||||
/**
|
||||
* Scaled down version of printf(3)
|
||||
*/
|
||||
int kvprintf(char const *fmt, void (*func) (int, void *), void *arg, int radix, va_list ap);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
50
hermit/arch/x86/loader/include/string.h
Normal file
50
hermit/arch/x86/loader/include/string.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __STRING_H__
|
||||
#define __STRING_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t count);
|
||||
void *memset(void *dest, int val, size_t count);
|
||||
size_t strlen(const char *str);
|
||||
char *strncpy(char *dest, const char *src, size_t n);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
int strncmp(const char *s1, const char *s2, size_t n);
|
||||
char *strstr(const char *s, const char *find);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
61
hermit/arch/x86/loader/include/vga.h
Normal file
61
hermit/arch/x86/loader/include/vga.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __VGA_H__
|
||||
#define __VGA_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Initialize VGA output and clear the screen */
|
||||
void vga_init(void);
|
||||
|
||||
/** @brief Simple string output on screen.
|
||||
*
|
||||
* If you want a new line you will have to "\\n".
|
||||
*
|
||||
* @return Length of output in bytes
|
||||
*/
|
||||
int vga_puts(const char *text);
|
||||
|
||||
/** @brief Simple character output on screen.
|
||||
*
|
||||
* @return The original input character casted to int
|
||||
*/
|
||||
int vga_putchar(unsigned char c);
|
||||
|
||||
/** @brief Clear the screen */
|
||||
void vga_cls(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
28
hermit/arch/x86/loader/link.ld
Normal file
28
hermit/arch/x86/loader/link.ld
Normal file
|
@ -0,0 +1,28 @@
|
|||
OUTPUT_FORMAT("elf64-x86-64")
|
||||
OUTPUT_ARCH("i386:x86-64")
|
||||
ENTRY(start)
|
||||
phys = 0x000000100000;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
kernel_start = phys;
|
||||
.mboot phys : AT(ADDR(.mboot)) {
|
||||
*(.mboot)
|
||||
}
|
||||
.text ALIGN(4096) : AT(ADDR(.text)) {
|
||||
*(.text)
|
||||
}
|
||||
.rodata ALIGN(4096) : AT(ADDR(.rodata)) {
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
}
|
||||
.data ALIGN(4096) : AT(ADDR(.data)) {
|
||||
*(.data)
|
||||
}
|
||||
.bss ALIGN(4096) : AT(ADDR(.bss)) {
|
||||
bss_start = .;
|
||||
*(.bss)
|
||||
}
|
||||
bss_end = .;
|
||||
kernel_end = .;
|
||||
}
|
171
hermit/arch/x86/loader/main.c
Normal file
171
hermit/arch/x86/loader/main.c
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <multiboot.h>
|
||||
#include <elf.h>
|
||||
#include <page.h>
|
||||
|
||||
/*
|
||||
* Note that linker symbols are not variables, they have no memory allocated for
|
||||
* maintaining a value, rather their address is their value.
|
||||
*/
|
||||
extern const void kernel_start;
|
||||
extern const void kernel_end;
|
||||
extern const void bss_start;
|
||||
extern const void bss_end;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
elf_header_t* header = NULL;
|
||||
|
||||
// initialize .bss section
|
||||
memset((void*)&bss_start, 0x00, ((size_t) &bss_end - (size_t) &bss_start));
|
||||
|
||||
koutput_init();
|
||||
kputs("HermitCore loader...\n");
|
||||
kprintf("Loader starts at %p and ends at %p\n", &kernel_start, &kernel_end);
|
||||
|
||||
page_init();
|
||||
|
||||
if (mb_info) {
|
||||
if (mb_info->flags & MULTIBOOT_INFO_MEM_MAP) {
|
||||
size_t end_addr, start_addr;
|
||||
multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) ((size_t) mb_info->mmap_addr);
|
||||
multiboot_memory_map_t* mmap_end = (void*) ((size_t) mb_info->mmap_addr + mb_info->mmap_length);
|
||||
|
||||
// mark available memory as free
|
||||
while (mmap < mmap_end) {
|
||||
if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) {
|
||||
/* set the available memory as "unused" */
|
||||
start_addr = mmap->addr;
|
||||
end_addr = start_addr + mmap->len;
|
||||
|
||||
kprintf("Free region 0x%zx - 0x%zx\n", start_addr, end_addr);
|
||||
}
|
||||
mmap = (multiboot_memory_map_t*) ((size_t) mmap + sizeof(uint32_t) + mmap->size);
|
||||
}
|
||||
} else {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (mb_info->flags & MULTIBOOT_INFO_MODS) {
|
||||
if (!mb_info->mods_count) {
|
||||
kputs("Ups, we need at least one module!\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
// per default the first module is our HermitCore binary
|
||||
multiboot_module_t* mmodule = (multiboot_module_t*) ((size_t) mb_info->mods_addr);
|
||||
header = (elf_header_t*) ((size_t) mmodule[0].mod_start);
|
||||
kprintf("ELF file is located at %p\n", header);
|
||||
}
|
||||
} else {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (BUILTIN_EXPECT(!header, 0))
|
||||
goto failed;
|
||||
|
||||
if (BUILTIN_EXPECT(header->ident.magic != ELF_MAGIC, 0))
|
||||
goto invalid;
|
||||
|
||||
if (BUILTIN_EXPECT(header->type != ELF_ET_EXEC, 0))
|
||||
goto invalid;
|
||||
|
||||
if (BUILTIN_EXPECT(header->machine != ELF_EM_X86_64, 0))
|
||||
goto invalid;
|
||||
|
||||
if (BUILTIN_EXPECT(header->ident._class != ELF_CLASS_64, 0))
|
||||
goto invalid;
|
||||
|
||||
if (BUILTIN_EXPECT(header->ident.data != ELF_DATA_2LSB, 0))
|
||||
goto invalid;
|
||||
|
||||
if (header->ident.pad[0] != 0x42) {
|
||||
kprintf("ELF file doesn't contain a HermitCore application (OS/ABI 0x%x)\n", (uint32_t)header->ident.pad[0]);
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
for (int i=0; i<header->ph_entry_count; i++) {
|
||||
elf_program_header_t* prog_header;
|
||||
|
||||
prog_header = (elf_program_header_t*) (header->ph_offset+i*header->ph_entry_size+(size_t)header);
|
||||
|
||||
switch(prog_header->type)
|
||||
{
|
||||
case ELF_PT_LOAD: { // load program segment
|
||||
size_t viraddr = prog_header->virt_addr;
|
||||
size_t phyaddr = prog_header->offset + (size_t)header;
|
||||
|
||||
uint32_t npages = (prog_header->file_size >> PAGE_BITS);
|
||||
if (prog_header->file_size & (PAGE_SIZE-1))
|
||||
npages++;
|
||||
|
||||
kprintf("Map %u pages from physical start address 0x%zx linear to 0x%zx\n", npages, phyaddr, viraddr);
|
||||
int ret = page_map(viraddr, phyaddr, npages, PG_GLOBAL|PG_RW);
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
*((uint64_t*) (viraddr + 0x08)) = phyaddr; // physical start address
|
||||
*((uint32_t*) (viraddr + 0x1C)) = 0; // apicid;
|
||||
*((uint32_t*) (viraddr + 0x24)) = 1; // number of used cpus
|
||||
*((uint64_t*) (viraddr + 0x38)) = prog_header->file_size;
|
||||
*((uint32_t*) (viraddr + 0x60)) = 1; // numa nodes
|
||||
*((uint32_t*) (viraddr + 0x30)) = 0; // apicid
|
||||
}
|
||||
break;
|
||||
case ELF_PT_GNU_STACK: // Indicates stack executability => nothing todo
|
||||
break;
|
||||
default:
|
||||
kprintf("Unknown type %d\n", prog_header->type);
|
||||
}
|
||||
}
|
||||
|
||||
kprintf("Entry point: 0x%zx\n", header->entry);
|
||||
// jump to the HermitCore app
|
||||
asm volatile ("jmp *%0" :: "r"(header->entry) : "memory");
|
||||
|
||||
// we should never reach this point
|
||||
while(1);
|
||||
|
||||
failed:
|
||||
kputs("Upps, kernel panic!\n");
|
||||
while(1);
|
||||
|
||||
invalid:
|
||||
kprintf("Invalid executable!\n");
|
||||
kprintf("magic number 0x%x\n", (uint32_t) header->ident.magic);
|
||||
kprintf("header type 0x%x\n", (uint32_t) header->type);
|
||||
kprintf("machine type 0x%x\n", (uint32_t) header->machine);
|
||||
kprintf("elf ident class 0x%x\n", (uint32_t) header->ident._class);
|
||||
kprintf("elf identdata 0x%x\n", header->ident.data);
|
||||
kprintf("program entry point 0x%lx\n", (size_t) header->entry);
|
||||
while(1);
|
||||
}
|
222
hermit/arch/x86/loader/page.c
Normal file
222
hermit/arch/x86/loader/page.c
Normal file
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* 2014, Steffen Vogel, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a 32/64 bit portable paging implementation for the x86 architecture
|
||||
* using self-referenced page tables i.
|
||||
* See http://www.noteblok.net/2014/06/14/bachelor/ for a detailed description.
|
||||
*
|
||||
* @author Steffen Vogel <steffen.vogel@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <page.h>
|
||||
#include <multiboot.h>
|
||||
|
||||
/* Note that linker symbols are not variables, they have no memory
|
||||
* allocated for maintaining a value, rather their address is their value. */
|
||||
extern const void kernel_start;
|
||||
extern const void kernel_end;
|
||||
|
||||
/// This page is reserved for copying
|
||||
#define PAGE_TMP (PAGE_FLOOR((size_t) &kernel_start) - PAGE_SIZE)
|
||||
|
||||
/** This PGD table is initialized in entry.asm */
|
||||
extern size_t* boot_map;
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/** A self-reference enables direct access to all page tables */
|
||||
static size_t * const self[PAGE_LEVELS] = {
|
||||
(size_t *) 0xFFC00000,
|
||||
(size_t *) 0xFFFFF000
|
||||
};
|
||||
|
||||
/** An other self-reference for page_map_copy() */
|
||||
static size_t * const other[PAGE_LEVELS] = {
|
||||
(size_t *) 0xFF800000,
|
||||
(size_t *) 0xFFFFE000
|
||||
};
|
||||
#elif defined(CONFIG_X86_64)
|
||||
/** A self-reference enables direct access to all page tables */
|
||||
static size_t* const self[PAGE_LEVELS] = {
|
||||
(size_t *) 0xFFFFFF8000000000,
|
||||
(size_t *) 0xFFFFFFFFC0000000,
|
||||
(size_t *) 0xFFFFFFFFFFE00000,
|
||||
(size_t *) 0xFFFFFFFFFFFFF000
|
||||
};
|
||||
|
||||
/** An other self-reference for page_map_copy() */
|
||||
static size_t * const other[PAGE_LEVELS] = {
|
||||
(size_t *) 0xFFFFFF0000000000,
|
||||
(size_t *) 0xFFFFFFFF80000000,
|
||||
(size_t *) 0xFFFFFFFFFFC00000,
|
||||
(size_t *) 0xFFFFFFFFFFFFE000
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @brief Flush a specific page entry in TLB
|
||||
* * @param addr The (virtual) address of the page to flush
|
||||
* */
|
||||
static inline void tlb_flush_one_page(size_t addr)
|
||||
{
|
||||
asm volatile("invlpg (%0)" : : "r"(addr) : "memory");
|
||||
}
|
||||
|
||||
size_t virt_to_phys(size_t addr)
|
||||
{
|
||||
size_t vpn = addr >> PAGE_BITS; // virtual page number
|
||||
size_t entry = self[0][vpn]; // page table entry
|
||||
size_t off = addr & ~PAGE_MASK; // offset within page
|
||||
size_t phy = entry & PAGE_MASK; // physical page frame number
|
||||
|
||||
return phy | off;
|
||||
}
|
||||
|
||||
static size_t first_page = (size_t) &kernel_start - PAGE_SIZE;
|
||||
|
||||
size_t get_page(void)
|
||||
{
|
||||
size_t ret = first_page;
|
||||
|
||||
first_page += PAGE_SIZE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int page_map(size_t viraddr, size_t phyaddr, size_t npages, size_t bits)
|
||||
{
|
||||
int lvl, ret = -1;
|
||||
long vpn = viraddr >> PAGE_BITS;
|
||||
long first[PAGE_LEVELS], last[PAGE_LEVELS];
|
||||
|
||||
/* Calculate index boundaries for page map traversal */
|
||||
for (lvl=0; lvl<PAGE_LEVELS; lvl++) {
|
||||
first[lvl] = (vpn ) >> (lvl * PAGE_MAP_BITS);
|
||||
last[lvl] = (vpn+npages-1) >> (lvl * PAGE_MAP_BITS);
|
||||
}
|
||||
|
||||
/* Start iterating through the entries
|
||||
* beginning at the root table (PGD or PML4) */
|
||||
for (lvl=PAGE_LEVELS-1; lvl>=0; lvl--) {
|
||||
for (vpn=first[lvl]; vpn<=last[lvl]; vpn++) {
|
||||
if (lvl) { /* PML4, PDPT, PGD */
|
||||
if (!(self[lvl][vpn] & PG_PRESENT)) {
|
||||
/* There's no table available which covers the region.
|
||||
* Therefore we need to create a new empty table. */
|
||||
size_t phyaddr = get_page();
|
||||
if (BUILTIN_EXPECT(!phyaddr, 0))
|
||||
goto out;
|
||||
|
||||
/* Reference the new table within its parent */
|
||||
#ifdef CONFIG_X86_32
|
||||
self[lvl][vpn] = phyaddr | bits | PG_PRESENT | PG_USER | PG_RW;
|
||||
#elif defined(CONFIG_X86_64)
|
||||
self[lvl][vpn] = (phyaddr | bits | PG_PRESENT | PG_USER | PG_RW) & ~PG_XD;
|
||||
#endif
|
||||
|
||||
/* Fill new table with zeros */
|
||||
memset(&self[lvl-1][vpn<<PAGE_MAP_BITS], 0, PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
else { /* PGT */
|
||||
if (self[lvl][vpn] & PG_PRESENT)
|
||||
/* There's already a page mapped at this address.
|
||||
* We have to flush a single TLB entry. */
|
||||
tlb_flush_one_page(vpn << PAGE_BITS);
|
||||
|
||||
self[lvl][vpn] = phyaddr | bits | PG_PRESENT;
|
||||
phyaddr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Tables are freed by page_map_drop() */
|
||||
int page_unmap(size_t viraddr, size_t npages)
|
||||
{
|
||||
/* We aquire both locks for kernel and task tables
|
||||
* as we dont know to which the region belongs. */
|
||||
|
||||
/* Start iterating through the entries.
|
||||
* Only the PGT entries are removed. Tables remain allocated. */
|
||||
size_t vpn, start = viraddr>>PAGE_BITS;
|
||||
for (vpn=start; vpn<start+npages; vpn++)
|
||||
self[0][vpn] = 0;
|
||||
|
||||
|
||||
/* This can't fail because we don't make checks here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int page_init(void)
|
||||
{
|
||||
/* Map multiboot information and modules */
|
||||
if (mb_info) {
|
||||
size_t addr, npages;
|
||||
int ret;
|
||||
|
||||
// already mapped => entry.asm
|
||||
//addr = (size_t) mb_info & PAGE_MASK;
|
||||
//npages = PAGE_FLOOR(sizeof(*mb_info)) >> PAGE_BITS;
|
||||
//page_map(addr, addr, npages, PG_GLOBAL);
|
||||
|
||||
if (mb_info->flags & MULTIBOOT_INFO_MODS) {
|
||||
addr = mb_info->mods_addr;
|
||||
npages = PAGE_FLOOR(mb_info->mods_count*sizeof(multiboot_module_t)) >> PAGE_BITS;
|
||||
ret = page_map(addr, addr, npages, PG_GLOBAL);
|
||||
kprintf("Map module info at 0x%lx (ret %d)\n", addr, ret);
|
||||
|
||||
multiboot_module_t* mmodule = (multiboot_module_t*) ((size_t) mb_info->mods_addr);
|
||||
|
||||
// at first we determine the first free page
|
||||
for(int i=0; i<mb_info->mods_count; i++) {
|
||||
if (first_page < mmodule[i].mod_end)
|
||||
first_page = PAGE_FLOOR(mmodule[i].mod_end);
|
||||
}
|
||||
|
||||
// we map only the first page of each module (= ELF file) because
|
||||
// we need only the program header of the ELF file
|
||||
for(int i=0; i<mb_info->mods_count; i++) {
|
||||
addr = mmodule[i].mod_start;
|
||||
//npages = PAGE_FLOOR(mmodule[i].mod_end - mmodule[i].mod_start) >> PAGE_BITS;
|
||||
ret = page_map(addr, addr, 1 /*npages*/, PG_GLOBAL);
|
||||
kprintf("Map first page of module %d at 0x%lx (ret %d)\n", i, addr, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kprintf("Page pool starts at 0x%zx\n", first_page);
|
||||
|
||||
return 0;
|
||||
}
|
485
hermit/arch/x86/loader/printf.c
Normal file
485
hermit/arch/x86/loader/printf.c
Normal file
|
@ -0,0 +1,485 @@
|
|||
/*-
|
||||
* Copyright (c) 1986, 1988, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* printf implementation is based on a implementation which was
|
||||
* published at http://www.pagetable.com/?p=298.
|
||||
* The authors built a full-featured standalone version of printf(). The
|
||||
* base code has been taken from FreeBSD (sys/kern/subr_prf.c) and is
|
||||
* consequently BSD-licensed. Unnecessary functions have been removed and
|
||||
* all typedefs required have been added.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define __64BIT__
|
||||
|
||||
#ifdef __64BIT__
|
||||
typedef unsigned long long uintmax_t;
|
||||
typedef long long intmax_t;
|
||||
#else
|
||||
typedef unsigned int uintmax_t;
|
||||
typedef int intmax_t;
|
||||
#endif
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned long u_long;
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned long long u_quad_t;
|
||||
typedef long long quad_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
#define NBBY 8 /* number of bits in a byte */
|
||||
char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
#define hex2ascii(hex) (hex2ascii_data[hex])
|
||||
#define va_list __builtin_va_list
|
||||
#define va_start __builtin_va_start
|
||||
#define va_arg __builtin_va_arg
|
||||
#define va_end __builtin_va_end
|
||||
#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
|
||||
|
||||
/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
|
||||
#define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
|
||||
|
||||
/*
|
||||
* Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
|
||||
* order; return an optional length and a pointer to the last character
|
||||
* written in the buffer (i.e., the first character of the string).
|
||||
* The buffer pointed to by `nbuf' must have length >= MAXNBUF.
|
||||
*/
|
||||
static char *ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
|
||||
{
|
||||
char *p, c;
|
||||
|
||||
p = nbuf;
|
||||
*p = '\0';
|
||||
do {
|
||||
c = hex2ascii(num % base);
|
||||
*++p = upper ? toupper(c) : c;
|
||||
} while (num /= base);
|
||||
if (lenp)
|
||||
*lenp = p - nbuf;
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scaled down version of printf(3).
|
||||
*
|
||||
* Two additional formats:
|
||||
*
|
||||
* The format %b is supported to decode error registers.
|
||||
* Its usage is:
|
||||
*
|
||||
* printf("reg=%b\n", regval, "*");
|
||||
*
|
||||
* where the output base is expressed as a control character, e.g.
|
||||
* \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
|
||||
* the first of which gives the bit number to be inspected (origin 1), and
|
||||
* the next characters (up to a control character, i.e. a character <= 32),
|
||||
* give the name of the register. Thus:
|
||||
*
|
||||
* kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
|
||||
*
|
||||
* would produce output:
|
||||
*
|
||||
* reg=3
|
||||
*
|
||||
* XXX: %D -- Hexdump, takes pointer and separator string:
|
||||
* ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
|
||||
* ("%*D", len, ptr, " " -> XX XX XX XX ...
|
||||
*/
|
||||
int kvprintf(char const *fmt, void (*func) (int, void *), void *arg, int radix,
|
||||
va_list ap)
|
||||
{
|
||||
#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
|
||||
char nbuf[MAXNBUF];
|
||||
char *d;
|
||||
const char *p, *percent, *q;
|
||||
u_char *up;
|
||||
int ch, n;
|
||||
uintmax_t num;
|
||||
int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
|
||||
int cflag, hflag, jflag, tflag, zflag;
|
||||
int dwidth, upper;
|
||||
char padc;
|
||||
int stop = 0, retval = 0;
|
||||
|
||||
num = 0;
|
||||
if (!func)
|
||||
d = (char *)arg;
|
||||
else
|
||||
d = NULL;
|
||||
|
||||
if (fmt == NULL)
|
||||
fmt = "(fmt null)\n";
|
||||
|
||||
if (radix < 2 || radix > 36)
|
||||
radix = 10;
|
||||
|
||||
for (;;) {
|
||||
padc = ' ';
|
||||
width = 0;
|
||||
while ((ch = (u_char) * fmt++) != '%' || stop) {
|
||||
if (ch == '\0')
|
||||
return (retval);
|
||||
PCHAR(ch);
|
||||
}
|
||||
percent = fmt - 1;
|
||||
qflag = 0;
|
||||
lflag = 0;
|
||||
ladjust = 0;
|
||||
sharpflag = 0;
|
||||
neg = 0;
|
||||
sign = 0;
|
||||
dot = 0;
|
||||
dwidth = 0;
|
||||
upper = 0;
|
||||
cflag = 0;
|
||||
hflag = 0;
|
||||
jflag = 0;
|
||||
tflag = 0;
|
||||
zflag = 0;
|
||||
reswitch: switch (ch = (u_char) * fmt++) {
|
||||
case '.':
|
||||
dot = 1;
|
||||
goto reswitch;
|
||||
case '#':
|
||||
sharpflag = 1;
|
||||
goto reswitch;
|
||||
case '+':
|
||||
sign = 1;
|
||||
goto reswitch;
|
||||
case '-':
|
||||
ladjust = 1;
|
||||
goto reswitch;
|
||||
case '%':
|
||||
PCHAR(ch);
|
||||
break;
|
||||
case '*':
|
||||
if (!dot) {
|
||||
width = va_arg(ap, int);
|
||||
if (width < 0) {
|
||||
ladjust = !ladjust;
|
||||
width = -width;
|
||||
}
|
||||
} else {
|
||||
dwidth = va_arg(ap, int);
|
||||
}
|
||||
goto reswitch;
|
||||
case '0':
|
||||
if (!dot) {
|
||||
padc = '0';
|
||||
goto reswitch;
|
||||
}
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
for (n = 0;; ++fmt) {
|
||||
n = n * 10 + ch - '0';
|
||||
ch = *fmt;
|
||||
if (ch < '0' || ch > '9')
|
||||
break;
|
||||
}
|
||||
if (dot)
|
||||
dwidth = n;
|
||||
else
|
||||
width = n;
|
||||
goto reswitch;
|
||||
case 'b':
|
||||
num = (u_int) va_arg(ap, int);
|
||||
p = va_arg(ap, char *);
|
||||
for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
|
||||
PCHAR(*q--);
|
||||
|
||||
if (num == 0)
|
||||
break;
|
||||
|
||||
for (tmp = 0; *p;) {
|
||||
n = *p++;
|
||||
if (num & (1 << (n - 1))) {
|
||||
PCHAR(tmp ? ',' : '<');
|
||||
for (; (n = *p) > ' '; ++p)
|
||||
PCHAR(n);
|
||||
tmp = 1;
|
||||
} else
|
||||
for (; *p > ' '; ++p)
|
||||
continue;
|
||||
}
|
||||
if (tmp)
|
||||
PCHAR('>');
|
||||
break;
|
||||
case 'c':
|
||||
PCHAR(va_arg(ap, int));
|
||||
break;
|
||||
case 'D':
|
||||
up = va_arg(ap, u_char *);
|
||||
p = va_arg(ap, char *);
|
||||
if (!width)
|
||||
width = 16;
|
||||
while (width--) {
|
||||
PCHAR(hex2ascii(*up >> 4));
|
||||
PCHAR(hex2ascii(*up & 0x0f));
|
||||
up++;
|
||||
if (width)
|
||||
for (q = p; *q; q++)
|
||||
PCHAR(*q);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
case 'i':
|
||||
base = 10;
|
||||
sign = 1;
|
||||
goto handle_sign;
|
||||
case 'h':
|
||||
if (hflag) {
|
||||
hflag = 0;
|
||||
cflag = 1;
|
||||
} else
|
||||
hflag = 1;
|
||||
goto reswitch;
|
||||
case 'j':
|
||||
jflag = 1;
|
||||
goto reswitch;
|
||||
case 'l':
|
||||
if (lflag) {
|
||||
lflag = 0;
|
||||
qflag = 1;
|
||||
} else
|
||||
lflag = 1;
|
||||
goto reswitch;
|
||||
case 'n':
|
||||
if (jflag)
|
||||
*(va_arg(ap, intmax_t *)) = retval;
|
||||
else if (qflag)
|
||||
*(va_arg(ap, quad_t *)) = retval;
|
||||
else if (lflag)
|
||||
*(va_arg(ap, long *)) = retval;
|
||||
else if (zflag)
|
||||
*(va_arg(ap, size_t *)) = retval;
|
||||
else if (hflag)
|
||||
*(va_arg(ap, short *)) = retval;
|
||||
else if (cflag)
|
||||
*(va_arg(ap, char *)) = retval;
|
||||
else
|
||||
*(va_arg(ap, int *)) = retval;
|
||||
break;
|
||||
case 'o':
|
||||
base = 8;
|
||||
goto handle_nosign;
|
||||
case 'p':
|
||||
base = 16;
|
||||
sharpflag = (width == 0);
|
||||
sign = 0;
|
||||
num = (uintptr_t) va_arg(ap, void *);
|
||||
goto number;
|
||||
case 'q':
|
||||
qflag = 1;
|
||||
goto reswitch;
|
||||
case 'r':
|
||||
base = radix;
|
||||
if (sign)
|
||||
goto handle_sign;
|
||||
goto handle_nosign;
|
||||
case 's':
|
||||
p = va_arg(ap, char *);
|
||||
if (p == NULL)
|
||||
p = "(null)";
|
||||
if (!dot)
|
||||
n = strlen(p);
|
||||
else
|
||||
for (n = 0; n < dwidth && p[n]; n++)
|
||||
continue;
|
||||
|
||||
width -= n;
|
||||
|
||||
if (!ladjust && width > 0)
|
||||
while (width--)
|
||||
PCHAR(padc);
|
||||
while (n--)
|
||||
PCHAR(*p++);
|
||||
if (ladjust && width > 0)
|
||||
while (width--)
|
||||
PCHAR(padc);
|
||||
break;
|
||||
case 't':
|
||||
tflag = 1;
|
||||
goto reswitch;
|
||||
case 'u':
|
||||
base = 10;
|
||||
goto handle_nosign;
|
||||
case 'X':
|
||||
upper = 1;
|
||||
case 'x':
|
||||
base = 16;
|
||||
goto handle_nosign;
|
||||
case 'y':
|
||||
base = 16;
|
||||
sign = 1;
|
||||
goto handle_sign;
|
||||
case 'z':
|
||||
zflag = 1;
|
||||
goto reswitch;
|
||||
handle_nosign:
|
||||
sign = 0;
|
||||
if (jflag)
|
||||
num = va_arg(ap, uintmax_t);
|
||||
else if (qflag)
|
||||
num = va_arg(ap, u_quad_t);
|
||||
else if (tflag)
|
||||
num = va_arg(ap, ptrdiff_t);
|
||||
else if (lflag)
|
||||
num = va_arg(ap, u_long);
|
||||
else if (zflag)
|
||||
num = va_arg(ap, size_t);
|
||||
else if (hflag)
|
||||
num = (u_short) va_arg(ap, int);
|
||||
else if (cflag)
|
||||
num = (u_char) va_arg(ap, int);
|
||||
else
|
||||
num = va_arg(ap, u_int);
|
||||
goto number;
|
||||
handle_sign:
|
||||
if (jflag)
|
||||
num = va_arg(ap, intmax_t);
|
||||
else if (qflag)
|
||||
num = va_arg(ap, quad_t);
|
||||
else if (tflag)
|
||||
num = va_arg(ap, ptrdiff_t);
|
||||
else if (lflag)
|
||||
num = va_arg(ap, long);
|
||||
else if (zflag)
|
||||
num = va_arg(ap, ssize_t);
|
||||
else if (hflag)
|
||||
num = (short)va_arg(ap, int);
|
||||
else if (cflag)
|
||||
num = (char)va_arg(ap, int);
|
||||
else
|
||||
num = va_arg(ap, int);
|
||||
number:
|
||||
if (sign && (intmax_t) num < 0) {
|
||||
neg = 1;
|
||||
num = -(intmax_t) num;
|
||||
}
|
||||
p = ksprintn(nbuf, num, base, &tmp, upper);
|
||||
if (sharpflag && num != 0) {
|
||||
if (base == 8)
|
||||
tmp++;
|
||||
else if (base == 16)
|
||||
tmp += 2;
|
||||
}
|
||||
if (neg)
|
||||
tmp++;
|
||||
|
||||
if (!ladjust && padc != '0' && width
|
||||
&& (width -= tmp) > 0)
|
||||
while (width--)
|
||||
PCHAR(padc);
|
||||
if (neg)
|
||||
PCHAR('-');
|
||||
if (sharpflag && num != 0) {
|
||||
if (base == 8) {
|
||||
PCHAR('0');
|
||||
} else if (base == 16) {
|
||||
PCHAR('0');
|
||||
PCHAR('x');
|
||||
}
|
||||
}
|
||||
if (!ladjust && width && (width -= tmp) > 0)
|
||||
while (width--)
|
||||
PCHAR(padc);
|
||||
|
||||
while (*p)
|
||||
PCHAR(*p--);
|
||||
|
||||
if (ladjust && width && (width -= tmp) > 0)
|
||||
while (width--)
|
||||
PCHAR(padc);
|
||||
|
||||
break;
|
||||
default:
|
||||
while (percent < fmt)
|
||||
PCHAR(*percent++);
|
||||
/*
|
||||
* Since we ignore a formatting argument it is no
|
||||
* longer safe to obey the remaining formatting
|
||||
* arguments as the arguments will no longer match
|
||||
* the format specs.
|
||||
*/
|
||||
stop = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#undef PCHAR
|
||||
}
|
||||
|
||||
/*
|
||||
* Print directly a character on the screen
|
||||
*/
|
||||
extern int kputchar(int);
|
||||
|
||||
/*
|
||||
* A wrapper function for kputchar because
|
||||
* kvprintf needs an output function, which possesses two arguments.
|
||||
* The first arguments defines the output character, the second could be used to pass
|
||||
* additional arguments. In the case of kputchar is no additional argument needed.
|
||||
*/
|
||||
static void _putchar(int c, void *arg)
|
||||
{
|
||||
kputchar(c);
|
||||
}
|
||||
|
||||
int kprintf(const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* http://www.pagetable.com/?p=298 */
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = kvprintf(fmt,
|
||||
_putchar, /* output function */
|
||||
NULL, /* additional argument for the output function */
|
||||
10, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
58
hermit/arch/x86/loader/stdio.c
Normal file
58
hermit/arch/x86/loader/stdio.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <multiboot.h>
|
||||
#include <vga.h>
|
||||
|
||||
int koutput_init(void)
|
||||
{
|
||||
vga_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kputchar(int c)
|
||||
{
|
||||
vga_putchar(c);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kputs(const char *str)
|
||||
{
|
||||
#if 0
|
||||
int i, len = strlen(str);
|
||||
|
||||
for(i=0; i<len; i++)
|
||||
vga_putchar(str[i]);
|
||||
|
||||
return len;
|
||||
#else
|
||||
return vga_puts(str);
|
||||
#endif
|
||||
}
|
106
hermit/arch/x86/loader/string.c
Normal file
106
hermit/arch/x86/loader/string.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Written by the Chair for Operating Systems, RWTH Aachen University
|
||||
*
|
||||
* NO Copyright (C) 2010-2011, Stefan Lankes
|
||||
* consider these trivial functions to be public domain.
|
||||
*
|
||||
* These functions are distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (BUILTIN_EXPECT(!dest || !src, 0))
|
||||
return dest;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
((char*)dest)[i] = ((char*)src)[i];
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *dest, int val, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (BUILTIN_EXPECT(!dest, 0))
|
||||
return dest;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
((char*) dest)[i] = (char) val;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
size_t strlen(const char *str)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
if (BUILTIN_EXPECT(!str, 0))
|
||||
return len;
|
||||
|
||||
while (str[len] != '\0')
|
||||
len++;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
char* strncpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (BUILTIN_EXPECT(!dest || !src, 0))
|
||||
return dest;
|
||||
|
||||
for (i = 0 ; i < n && src[i] != '\0' ; i++)
|
||||
dest[i] = src[i];
|
||||
if (i < n)
|
||||
dest[i] = '\0';
|
||||
else
|
||||
dest[n-1] = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char* strcpy(char *dest, const char *src)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (BUILTIN_EXPECT(!dest || !src, 0))
|
||||
return dest;
|
||||
|
||||
for (i = 0 ; src[i] != '\0' ; i++)
|
||||
dest[i] = src[i];
|
||||
dest[i] = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 != '\0' && *s1 == *s2) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return (*(unsigned char *) s1) - (*(unsigned char *) s2);
|
||||
}
|
||||
|
||||
int strncmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
if (BUILTIN_EXPECT(n == 0, 0))
|
||||
return 0;
|
||||
|
||||
while (n-- != 0 && *s1 == *s2) {
|
||||
if (n == 0 || *s1 == '\0')
|
||||
break;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return (*(unsigned char *) s1) - (*(unsigned char *) s2);
|
||||
}
|
237
hermit/arch/x86/loader/vga.c
Normal file
237
hermit/arch/x86/loader/vga.c
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
#include <vga.h>
|
||||
|
||||
#define VIDEO_MEM_ADDR 0xB8000 /* the video memory address */
|
||||
|
||||
/*
|
||||
* These define our textpointer, our background and foreground
|
||||
* colors (attributes), and x and y cursor coordinates
|
||||
*/
|
||||
static unsigned short *textmemptr;
|
||||
static int attrib = 0x0F;
|
||||
static int csr_x = 0, csr_y = 0;
|
||||
|
||||
inline static unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (BUILTIN_EXPECT(!dest, 0))
|
||||
return dest;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
dest[i] = val;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Scrolls the screen */
|
||||
static void scroll(void)
|
||||
{
|
||||
unsigned blank, temp;
|
||||
|
||||
/*
|
||||
* A blank is defined as a space... we need to give it
|
||||
* backcolor too
|
||||
*/
|
||||
blank = 0x20 | (attrib << 8);
|
||||
|
||||
/* Row 25 is the end, this means we need to scroll up */
|
||||
if (csr_y >= 25) {
|
||||
|
||||
/*
|
||||
* Move the current text chunk that makes up the screen
|
||||
*
|
||||
* back in the buffer by one line
|
||||
*/
|
||||
temp = csr_y - 25 + 1;
|
||||
memcpy(textmemptr, textmemptr + temp * 80,
|
||||
(25 - temp) * 80 * 2);
|
||||
|
||||
/*
|
||||
* Finally, we set the chunk of memory that occupies
|
||||
* the last line of text to our 'blank' character
|
||||
*/
|
||||
memsetw(textmemptr + (25 - temp) * 80, blank, 80);
|
||||
csr_y = 25 - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates the hardware cursor: the little blinking line
|
||||
* on the screen under the last character pressed!
|
||||
*/
|
||||
static void move_csr(void)
|
||||
{
|
||||
unsigned temp;
|
||||
|
||||
/*
|
||||
* The equation for finding the index in a linear
|
||||
* chunk of memory can be represented by:
|
||||
* Index = [(y * width) + x] */
|
||||
temp = csr_y * 80 + csr_x;
|
||||
|
||||
/*
|
||||
* This sends a command to indicies 14 and 15 in the
|
||||
* CRT Control Register of the VGA controller. These
|
||||
* are the high and low bytes of the index that show
|
||||
* where the hardware cursor is to be 'blinking'. To
|
||||
* learn more, you should look up some VGA specific
|
||||
* programming documents. A great start to graphics:
|
||||
* http://www.brackeen.com/home/vga
|
||||
*/
|
||||
outportb(0x3D4, 14);
|
||||
outportb(0x3D5, temp >> 8);
|
||||
outportb(0x3D4, 15);
|
||||
outportb(0x3D5, temp);
|
||||
}
|
||||
|
||||
/* Clears the screen */
|
||||
void vga_clear(void)
|
||||
{
|
||||
unsigned blank;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Again, we need the 'short' that will be used to
|
||||
* represent a space with color
|
||||
*/
|
||||
blank = 0x20 | (attrib << 8);
|
||||
|
||||
/*
|
||||
* Fills the entire screen with spaces in our current
|
||||
* color
|
||||
**/
|
||||
for (i = 0; i < 25; i++)
|
||||
memsetw(textmemptr + i * 80, blank, 80);
|
||||
|
||||
/*
|
||||
* Update out virtual cursor, and then move the
|
||||
* hardware cursor
|
||||
*/
|
||||
csr_x = 0;
|
||||
csr_y = 0;
|
||||
move_csr();
|
||||
}
|
||||
|
||||
/* Puts a single character on the screen */
|
||||
int vga_putchar(unsigned char c)
|
||||
{
|
||||
unsigned short *where;
|
||||
unsigned att = attrib << 8;
|
||||
|
||||
/* Handle a backspace by moving the cursor back one space */
|
||||
if (c == 0x08) {
|
||||
if (csr_x != 0)
|
||||
csr_x--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles a tab by incrementing the cursor's x, but only
|
||||
* to a point that will make it divisible by 8
|
||||
*/
|
||||
else if (c == 0x09) {
|
||||
csr_x = (csr_x + 8) & ~(8 - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles a 'Carriage Return', which simply brings the
|
||||
* cursor back to the margin
|
||||
*/
|
||||
else if (c == '\r') {
|
||||
csr_x = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We handle our newlines the way DOS and BIOS do: we
|
||||
* treat it as if a 'CR' was there also, so we bring the
|
||||
* cursor to the margin and increment the 'y' value
|
||||
*/
|
||||
else if (c == '\n') {
|
||||
csr_x = 0;
|
||||
csr_y++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Any character greater than and including the space is a
|
||||
* printable character. The equation for finding the index
|
||||
* in a linear chunk of memory can be represented by:
|
||||
* Index = [(y * width) + x]
|
||||
*/
|
||||
else if (c >= ' ') {
|
||||
where = textmemptr + (csr_y * 80 + csr_x);
|
||||
*where = c | att; /* Character AND attributes: color */
|
||||
csr_x++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the cursor has reached the edge of the screen's width, we
|
||||
* insert a new line in there
|
||||
*/
|
||||
if (csr_x >= 80) {
|
||||
csr_x = 0;
|
||||
csr_y++;
|
||||
}
|
||||
|
||||
/* Scroll the screen if needed, and finally move the cursor */
|
||||
scroll();
|
||||
move_csr();
|
||||
|
||||
return (int) c;
|
||||
}
|
||||
|
||||
/* Uses the routine above to output a string... */
|
||||
int vga_puts(const char *text)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < strlen(text); i++)
|
||||
vga_putchar(text[i]);
|
||||
|
||||
return i-1;
|
||||
}
|
||||
|
||||
/* Sets the forecolor and backcolor we will use */
|
||||
//void settextcolor(unsigned char forecolor, unsigned char backcolor)
|
||||
//{
|
||||
|
||||
/*
|
||||
* Top 4 bytes are the background, bottom 4 bytes
|
||||
* are the foreground color
|
||||
*/
|
||||
// attrib = (backcolor << 4) | (forecolor & 0x0F);
|
||||
//}
|
||||
|
||||
/* Sets our text-mode VGA pointer, then clears the screen for us */
|
||||
void vga_init(void)
|
||||
{
|
||||
textmemptr = (unsigned short *)VIDEO_MEM_ADDR;
|
||||
vga_clear();
|
||||
}
|
Loading…
Add table
Reference in a new issue