Compare commits
17 Commits
a2b5e71654
...
31aa157201
Author | SHA1 | Date |
---|---|---|
Bananymous | 31aa157201 | |
Bananymous | 5977341610 | |
Bananymous | 76f17bd569 | |
Bananymous | 6b1b3d333c | |
Bananymous | cb65be3e33 | |
Bananymous | dafc016293 | |
Bananymous | c7b6fc950a | |
Bananymous | 45a6783c3d | |
Bananymous | 6b180da4e8 | |
Bananymous | cf4f5f64a5 | |
Bananymous | 5630f64175 | |
Bananymous | 1d61bccfc3 | |
Bananymous | f842a9255f | |
Bananymous | 72f3c378dd | |
Bananymous | 39be6ab099 | |
Bananymous | 773dcdd3a2 | |
Bananymous | f0820e6f24 |
|
@ -5,4 +5,5 @@ base/
|
||||||
*.tar.*
|
*.tar.*
|
||||||
toolchain/*/
|
toolchain/*/
|
||||||
|
|
||||||
|
!toolchain/local/
|
||||||
!base-sysroot.tar.gz
|
!base-sysroot.tar.gz
|
||||||
|
|
|
@ -22,6 +22,10 @@ if(DEFINED QEMU_ACCEL)
|
||||||
set(QEMU_ACCEL -accel ${QEMU_ACCEL})
|
set(QEMU_ACCEL -accel ${QEMU_ACCEL})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED UEFI_BOOT)
|
||||||
|
set(UEFI_BOOT 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_compile_options(-mno-sse -mno-sse2)
|
add_compile_options(-mno-sse -mno-sse2)
|
||||||
add_compile_definitions(__enable_sse=0)
|
add_compile_definitions(__enable_sse=0)
|
||||||
|
|
||||||
|
@ -67,7 +71,7 @@ add_custom_target(libstdc++
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(image
|
add_custom_target(image
|
||||||
COMMAND ${CMAKE_COMMAND} -E env SYSROOT="${BANAN_SYSROOT}" DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" ${CMAKE_SOURCE_DIR}/image.sh
|
COMMAND ${CMAKE_COMMAND} -E env BANAN_ARCH="${BANAN_ARCH}" SYSROOT="${BANAN_SYSROOT}" DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" TOOLCHAIN="${TOOLCHAIN_PREFIX}" UEFI_BOOT="${UEFI_BOOT}" ${CMAKE_SOURCE_DIR}/image.sh
|
||||||
DEPENDS kernel-install
|
DEPENDS kernel-install
|
||||||
DEPENDS ban-install
|
DEPENDS ban-install
|
||||||
DEPENDS libc-install
|
DEPENDS libc-install
|
||||||
|
@ -77,7 +81,7 @@ add_custom_target(image
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(image-full
|
add_custom_target(image-full
|
||||||
COMMAND ${CMAKE_COMMAND} -E env SYSROOT="${BANAN_SYSROOT}" DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" ${CMAKE_SOURCE_DIR}/image-full.sh
|
COMMAND ${CMAKE_COMMAND} -E env BANAN_ARCH="${BANAN_ARCH}" SYSROOT="${BANAN_SYSROOT}" DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" TOOLCHAIN="${TOOLCHAIN_PREFIX}" UEFI_BOOT="${UEFI_BOOT}" ${CMAKE_SOURCE_DIR}/image-full.sh
|
||||||
DEPENDS kernel-install
|
DEPENDS kernel-install
|
||||||
DEPENDS ban-install
|
DEPENDS ban-install
|
||||||
DEPENDS libc-install
|
DEPENDS libc-install
|
||||||
|
@ -92,19 +96,19 @@ add_custom_target(check-fs
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(qemu
|
add_custom_target(qemu
|
||||||
COMMAND ${CMAKE_COMMAND} -E env BANAN_ARCH="${BANAN_ARCH}" DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" ${CMAKE_SOURCE_DIR}/qemu.sh -serial stdio ${QEMU_ACCEL}
|
COMMAND ${CMAKE_COMMAND} -E env BANAN_ARCH="${BANAN_ARCH}" DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" UEFI_BOOT="${UEFI_BOOT}" ${CMAKE_SOURCE_DIR}/qemu.sh -serial stdio ${QEMU_ACCEL}
|
||||||
DEPENDS image
|
DEPENDS image
|
||||||
USES_TERMINAL
|
USES_TERMINAL
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(qemu-nographic
|
add_custom_target(qemu-nographic
|
||||||
COMMAND ${CMAKE_COMMAND} -E env BANAN_ARCH="${BANAN_ARCH}" DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" ${CMAKE_SOURCE_DIR}/qemu.sh -nographic ${QEMU_ACCEL}
|
COMMAND ${CMAKE_COMMAND} -E env BANAN_ARCH="${BANAN_ARCH}" DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" UEFI_BOOT="${UEFI_BOOT}" ${CMAKE_SOURCE_DIR}/qemu.sh -nographic ${QEMU_ACCEL}
|
||||||
DEPENDS image
|
DEPENDS image
|
||||||
USES_TERMINAL
|
USES_TERMINAL
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(qemu-debug
|
add_custom_target(qemu-debug
|
||||||
COMMAND ${CMAKE_COMMAND} -E env BANAN_ARCH="${BANAN_ARCH}" DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" ${CMAKE_SOURCE_DIR}/qemu.sh -serial stdio -d int -no-reboot
|
COMMAND ${CMAKE_COMMAND} -E env BANAN_ARCH="${BANAN_ARCH}" DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" UEFI_BOOT="${UEFI_BOOT}" ${CMAKE_SOURCE_DIR}/qemu.sh -serial stdio -d int -no-reboot
|
||||||
DEPENDS image
|
DEPENDS image
|
||||||
USES_TERMINAL
|
USES_TERMINAL
|
||||||
)
|
)
|
||||||
|
|
|
@ -27,6 +27,8 @@ namespace LibELF
|
||||||
|
|
||||||
LoadableELF::~LoadableELF()
|
LoadableELF::~LoadableELF()
|
||||||
{
|
{
|
||||||
|
if (!m_loaded)
|
||||||
|
return;
|
||||||
for (const auto& program_header : m_program_headers)
|
for (const auto& program_header : m_program_headers)
|
||||||
{
|
{
|
||||||
switch (program_header.p_type)
|
switch (program_header.p_type)
|
||||||
|
@ -155,6 +157,29 @@ namespace LibELF
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LoadableELF::is_address_space_free() const
|
||||||
|
{
|
||||||
|
for (const auto& program_header : m_program_headers)
|
||||||
|
{
|
||||||
|
switch (program_header.p_type)
|
||||||
|
{
|
||||||
|
case PT_NULL:
|
||||||
|
break;
|
||||||
|
case PT_LOAD:
|
||||||
|
{
|
||||||
|
vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||||
|
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||||
|
if (!m_page_table.is_range_free(page_vaddr, pages * PAGE_SIZE))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void LoadableELF::reserve_address_space()
|
void LoadableELF::reserve_address_space()
|
||||||
{
|
{
|
||||||
for (const auto& program_header : m_program_headers)
|
for (const auto& program_header : m_program_headers)
|
||||||
|
@ -174,6 +199,7 @@ namespace LibELF
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> LoadableELF::load_page_to_memory(vaddr_t address)
|
BAN::ErrorOr<void> LoadableELF::load_page_to_memory(vaddr_t address)
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace LibELF
|
||||||
Kernel::vaddr_t entry_point() const;
|
Kernel::vaddr_t entry_point() const;
|
||||||
|
|
||||||
bool contains(Kernel::vaddr_t address) const;
|
bool contains(Kernel::vaddr_t address) const;
|
||||||
|
bool is_address_space_free() const;
|
||||||
void reserve_address_space();
|
void reserve_address_space();
|
||||||
|
|
||||||
BAN::ErrorOr<void> load_page_to_memory(Kernel::vaddr_t address);
|
BAN::ErrorOr<void> load_page_to_memory(Kernel::vaddr_t address);
|
||||||
|
@ -47,6 +48,7 @@ namespace LibELF
|
||||||
BAN::Vector<ElfNativeProgramHeader> m_program_headers;
|
BAN::Vector<ElfNativeProgramHeader> m_program_headers;
|
||||||
size_t m_virtual_page_count = 0;
|
size_t m_virtual_page_count = 0;
|
||||||
size_t m_physical_page_count = 0;
|
size_t m_physical_page_count = 0;
|
||||||
|
bool m_loaded { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
Binary file not shown.
|
@ -4,29 +4,50 @@ set -e
|
||||||
DISK_SIZE=$[50 * 1024 * 1024]
|
DISK_SIZE=$[50 * 1024 * 1024]
|
||||||
MOUNT_DIR=/mnt
|
MOUNT_DIR=/mnt
|
||||||
|
|
||||||
truncate -s 0 $DISK_IMAGE_PATH
|
truncate -s 0 "$DISK_IMAGE_PATH"
|
||||||
truncate -s $DISK_SIZE $DISK_IMAGE_PATH
|
truncate -s $DISK_SIZE "$DISK_IMAGE_PATH"
|
||||||
|
|
||||||
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk $DISK_IMAGE_PATH > /dev/null
|
if [ "$UEFI_BOOT" == "1" ]; then
|
||||||
g # gpt
|
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk "$DISK_IMAGE_PATH" > /dev/null
|
||||||
n # new partition
|
g # gpt
|
||||||
1 # partition number 1
|
n # new partition
|
||||||
# default (from the beginning of the disk)
|
1 # partition number 1
|
||||||
+1MiB # bios boot partiton size
|
# default (from the beginning of the disk)
|
||||||
n # new partition
|
+16M # efi system size
|
||||||
2 # partition number 2
|
n # new partition
|
||||||
# default (right after bios boot partition)
|
2 # partition number 2
|
||||||
# default (to the end of disk)
|
# default (right after efi system partition)
|
||||||
t # set type
|
# default (to the end of disk)
|
||||||
1 # ... of partition 1
|
t # set type
|
||||||
4 # bios boot partition
|
1 # ... of partition 1
|
||||||
t # set type
|
1 # efi system
|
||||||
2 # ... of partition 2
|
t # set type
|
||||||
20 # Linux filesystem
|
2 # ... of partition 2
|
||||||
w # write changes
|
20 # Linux filesystem
|
||||||
|
w # write changes
|
||||||
EOF
|
EOF
|
||||||
|
else
|
||||||
|
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk "$DISK_IMAGE_PATH" > /dev/null
|
||||||
|
g # gpt
|
||||||
|
n # new partition
|
||||||
|
1 # partition number 1
|
||||||
|
# default (from the beginning of the disk)
|
||||||
|
+1M # bios boot partition size
|
||||||
|
n # new partition
|
||||||
|
2 # partition number 2
|
||||||
|
# default (right after bios partition)
|
||||||
|
# default (to the end of disk)
|
||||||
|
t # set type
|
||||||
|
1 # ... of partition 1
|
||||||
|
4 # bios boot partition
|
||||||
|
t # set type
|
||||||
|
2 # ... of partition 2
|
||||||
|
20 # Linux filesystem
|
||||||
|
w # write changes
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
LOOP_DEV=$(sudo losetup -f --show $DISK_IMAGE_PATH)
|
LOOP_DEV=$(sudo losetup -f --show "$DISK_IMAGE_PATH")
|
||||||
sudo partprobe $LOOP_DEV
|
sudo partprobe $LOOP_DEV
|
||||||
|
|
||||||
PARTITION1=${LOOP_DEV}p1
|
PARTITION1=${LOOP_DEV}p1
|
||||||
|
@ -34,8 +55,23 @@ PARTITION2=${LOOP_DEV}p2
|
||||||
|
|
||||||
sudo mkfs.ext2 -d $SYSROOT -b 1024 -q $PARTITION2
|
sudo mkfs.ext2 -d $SYSROOT -b 1024 -q $PARTITION2
|
||||||
|
|
||||||
sudo mount $PARTITION2 $MOUNT_DIR
|
if [[ "$UEFI_BOOT" == "1" ]]; then
|
||||||
sudo grub-install --no-floppy --target=i386-pc --modules="normal ext2 multiboot" --boot-directory=${MOUNT_DIR}/boot $LOOP_DEV
|
sudo mkfs.fat $PARTITION1 > /dev/null
|
||||||
sudo umount $MOUNT_DIR
|
sudo mount $PARTITION1 "$MOUNT_DIR"
|
||||||
|
sudo mkdir -p "$MOUNT_DIR/EFI/BOOT"
|
||||||
|
sudo "$TOOLCHAIN/bin/grub-mkstandalone" -O "$BANAN_ARCH-efi" -o "$MOUNT_DIR/EFI/BOOT/BOOTX64.EFI" "boot/grub/grub.cfg=$TOOLCHAIN/grub-memdisk.cfg"
|
||||||
|
sudo umount "$MOUNT_DIR"
|
||||||
|
|
||||||
|
sudo mount $PARTITION2 "$MOUNT_DIR"
|
||||||
|
sudo mkdir -p "$MOUNT_DIR/boot/grub"
|
||||||
|
sudo cp "$TOOLCHAIN/grub-uefi.cfg" "$MOUNT_DIR/boot/grub/grub.cfg"
|
||||||
|
sudo umount "$MOUNT_DIR"
|
||||||
|
else
|
||||||
|
sudo mount $PARTITION2 "$MOUNT_DIR"
|
||||||
|
sudo grub-install --no-floppy --target=i386-pc --modules="normal ext2 multiboot" --boot-directory="$MOUNT_DIR/boot" $LOOP_DEV
|
||||||
|
sudo mkdir -p "$MOUNT_DIR/boot/grub"
|
||||||
|
sudo cp "$TOOLCHAIN/grub-legacy-boot.cfg" "$MOUNT_DIR/boot/grub/grub.cfg"
|
||||||
|
sudo umount "$MOUNT_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
sudo losetup -d $LOOP_DEV
|
sudo losetup -d $LOOP_DEV
|
||||||
|
|
10
image.sh
10
image.sh
|
@ -1,11 +1,19 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ ! -f $DISK_IMAGE_PATH ]; then
|
if [ ! -f $DISK_IMAGE_PATH ]; then
|
||||||
$(dirname "$0")/image-full.sh
|
$(dirname "$0")/image-full.sh
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
fdisk -l $DISK_IMAGE_PATH | grep -q 'EFI System'; IMAGE_IS_UEFI=$?
|
||||||
|
[[ $UEFI_BOOT == 1 ]]; CREATE_IS_UEFI=$?
|
||||||
|
|
||||||
|
if [ $IMAGE_IS_UEFI -ne $CREATE_IS_UEFI ]; then
|
||||||
|
echo Converting disk image to/from UEFI
|
||||||
|
$(dirname "$0")/image-full.sh
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
MOUNT_DIR=/mnt
|
MOUNT_DIR=/mnt
|
||||||
|
|
||||||
LOOP_DEV=$(sudo losetup -f --show $DISK_IMAGE_PATH)
|
LOOP_DEV=$(sudo losetup -f --show $DISK_IMAGE_PATH)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include <BAN/Assert.h>
|
#include <BAN/Array.h>
|
||||||
#include <kernel/GDT.h>
|
#include <kernel/GDT.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -56,44 +56,44 @@ namespace Kernel::GDT
|
||||||
|
|
||||||
static constexpr uint16_t s_tss_offset = 0x28;
|
static constexpr uint16_t s_tss_offset = 0x28;
|
||||||
|
|
||||||
static TaskStateSegment* s_tss = nullptr;
|
static TaskStateSegment s_tss;
|
||||||
static SegmentDescriptor* s_gdt = nullptr;
|
static BAN::Array<SegmentDescriptor, 7> s_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
|
||||||
static GDTR s_gdtr;
|
static GDTR s_gdtr;
|
||||||
|
|
||||||
static void write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
static void write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
||||||
{
|
{
|
||||||
SegmentDescriptor& desc = *(SegmentDescriptor*)((uintptr_t)s_gdt + offset);
|
ASSERT(offset % sizeof(SegmentDescriptor) == 0);
|
||||||
desc.base1 = base;
|
|
||||||
desc.base2 = base >> 16;
|
|
||||||
desc.base3 = base >> 24;
|
|
||||||
|
|
||||||
desc.limit1 = limit;
|
SegmentDescriptor& desc = s_gdt[offset / sizeof(SegmentDescriptor)];
|
||||||
desc.limit2 = limit >> 16;
|
desc.base1 = (base >> 0) & 0xFFFF;
|
||||||
|
desc.base2 = (base >> 16) & 0xFF;
|
||||||
|
desc.base3 = (base >> 24) & 0xFF;
|
||||||
|
|
||||||
desc.access = access;
|
desc.limit1 = (limit >> 0) & 0xFFFF;
|
||||||
|
desc.limit2 = (limit >> 16) & 0x0F;
|
||||||
|
|
||||||
desc.flags = flags;
|
desc.access = access & 0xFF;
|
||||||
|
|
||||||
|
desc.flags = flags & 0x0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_tss()
|
static void write_tss()
|
||||||
{
|
{
|
||||||
s_tss = new TaskStateSegment();
|
memset(&s_tss, 0x00, sizeof(TaskStateSegment));
|
||||||
ASSERT(s_tss);
|
s_tss.iopb = sizeof(TaskStateSegment);
|
||||||
|
|
||||||
memset(s_tss, 0x00, sizeof(TaskStateSegment));
|
uint64_t base = (uint64_t)&s_tss;
|
||||||
s_tss->rsp0 = 0;
|
|
||||||
|
|
||||||
uintptr_t base = (uintptr_t)s_tss;
|
|
||||||
|
|
||||||
write_entry(s_tss_offset, (uint32_t)base, sizeof(TaskStateSegment), 0x89, 0x0);
|
write_entry(s_tss_offset, (uint32_t)base, sizeof(TaskStateSegment), 0x89, 0x0);
|
||||||
SegmentDescriptor& desc = *(SegmentDescriptor*)((uintptr_t)s_gdt + s_tss_offset + 0x08);
|
|
||||||
|
SegmentDescriptor& desc = s_gdt[s_tss_offset / sizeof(SegmentDescriptor) + 1];
|
||||||
desc.low = base >> 32;
|
desc.low = base >> 32;
|
||||||
desc.high = 0;
|
desc.high = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_tss_stack(uintptr_t rsp)
|
void set_tss_stack(uintptr_t rsp)
|
||||||
{
|
{
|
||||||
s_tss->rsp0 = rsp;
|
s_tss.rsp0 = rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flush_gdt()
|
static void flush_gdt()
|
||||||
|
@ -108,12 +108,8 @@ namespace Kernel::GDT
|
||||||
|
|
||||||
void initialize()
|
void initialize()
|
||||||
{
|
{
|
||||||
constexpr uint32_t descriptor_count = 6 + 1; // tss takes 2
|
s_gdtr.address = (uint64_t)&s_gdt;
|
||||||
s_gdt = new SegmentDescriptor[descriptor_count];
|
s_gdtr.size = s_gdt.size() * sizeof(SegmentDescriptor) - 1;
|
||||||
ASSERT(s_gdt);
|
|
||||||
|
|
||||||
s_gdtr.address = (uint64_t)s_gdt;
|
|
||||||
s_gdtr.size = descriptor_count * sizeof(SegmentDescriptor) - 1;
|
|
||||||
|
|
||||||
write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
||||||
write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, 0xA); // kernel code
|
write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, 0xA); // kernel code
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <BAN/Array.h>
|
||||||
#include <BAN/Errors.h>
|
#include <BAN/Errors.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
|
@ -8,10 +9,8 @@
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Timer/PIT.h>
|
#include <kernel/Timer/PIT.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#define ISR_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31)
|
||||||
|
#define IRQ_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31)
|
||||||
#define REGISTER_ISR_HANDLER(i) register_interrupt_handler(i, isr ## i)
|
|
||||||
#define REGISTER_IRQ_HANDLER(i) register_interrupt_handler(IRQ_VECTOR_BASE + i, irq ## i)
|
|
||||||
|
|
||||||
namespace Kernel::IDT
|
namespace Kernel::IDT
|
||||||
{
|
{
|
||||||
|
@ -63,7 +62,9 @@ namespace Kernel::IDT
|
||||||
static IDTR s_idtr;
|
static IDTR s_idtr;
|
||||||
static GateDescriptor* s_idt = nullptr;
|
static GateDescriptor* s_idt = nullptr;
|
||||||
|
|
||||||
static Interruptable* s_interruptables[0x10] {};
|
#define X(num) 1 +
|
||||||
|
static BAN::Array<Interruptable*, IRQ_LIST_X 0> s_interruptables;
|
||||||
|
#undef X
|
||||||
|
|
||||||
enum ISR
|
enum ISR
|
||||||
{
|
{
|
||||||
|
@ -356,58 +357,18 @@ done:
|
||||||
|
|
||||||
void register_irq_handler(uint8_t irq, Interruptable* interruptable)
|
void register_irq_handler(uint8_t irq, Interruptable* interruptable)
|
||||||
{
|
{
|
||||||
|
if (irq > s_interruptables.size())
|
||||||
|
Kernel::panic("Trying to assign handler for irq {} while only {} are supported", irq, s_interruptables.size());
|
||||||
s_interruptables[irq] = interruptable;
|
s_interruptables[irq] = interruptable;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void isr0();
|
#define X(num) extern "C" void isr ## num();
|
||||||
extern "C" void isr1();
|
ISR_LIST_X
|
||||||
extern "C" void isr2();
|
#undef X
|
||||||
extern "C" void isr3();
|
|
||||||
extern "C" void isr4();
|
|
||||||
extern "C" void isr5();
|
|
||||||
extern "C" void isr6();
|
|
||||||
extern "C" void isr7();
|
|
||||||
extern "C" void isr8();
|
|
||||||
extern "C" void isr9();
|
|
||||||
extern "C" void isr10();
|
|
||||||
extern "C" void isr11();
|
|
||||||
extern "C" void isr12();
|
|
||||||
extern "C" void isr13();
|
|
||||||
extern "C" void isr14();
|
|
||||||
extern "C" void isr15();
|
|
||||||
extern "C" void isr16();
|
|
||||||
extern "C" void isr17();
|
|
||||||
extern "C" void isr18();
|
|
||||||
extern "C" void isr19();
|
|
||||||
extern "C" void isr20();
|
|
||||||
extern "C" void isr21();
|
|
||||||
extern "C" void isr22();
|
|
||||||
extern "C" void isr23();
|
|
||||||
extern "C" void isr24();
|
|
||||||
extern "C" void isr25();
|
|
||||||
extern "C" void isr26();
|
|
||||||
extern "C" void isr27();
|
|
||||||
extern "C" void isr28();
|
|
||||||
extern "C" void isr29();
|
|
||||||
extern "C" void isr30();
|
|
||||||
extern "C" void isr31();
|
|
||||||
|
|
||||||
extern "C" void irq0();
|
#define X(num) extern "C" void irq ## num();
|
||||||
extern "C" void irq1();
|
IRQ_LIST_X
|
||||||
extern "C" void irq2();
|
#undef X
|
||||||
extern "C" void irq3();
|
|
||||||
extern "C" void irq4();
|
|
||||||
extern "C" void irq5();
|
|
||||||
extern "C" void irq6();
|
|
||||||
extern "C" void irq7();
|
|
||||||
extern "C" void irq8();
|
|
||||||
extern "C" void irq9();
|
|
||||||
extern "C" void irq10();
|
|
||||||
extern "C" void irq11();
|
|
||||||
extern "C" void irq12();
|
|
||||||
extern "C" void irq13();
|
|
||||||
extern "C" void irq14();
|
|
||||||
extern "C" void irq15();
|
|
||||||
|
|
||||||
extern "C" void syscall_asm();
|
extern "C" void syscall_asm();
|
||||||
|
|
||||||
|
@ -420,55 +381,13 @@ done:
|
||||||
s_idtr.offset = (uint64_t)s_idt;
|
s_idtr.offset = (uint64_t)s_idt;
|
||||||
s_idtr.size = 0x100 * sizeof(GateDescriptor) - 1;
|
s_idtr.size = 0x100 * sizeof(GateDescriptor) - 1;
|
||||||
|
|
||||||
REGISTER_ISR_HANDLER(0);
|
#define X(num) register_interrupt_handler(num, isr ## num);
|
||||||
REGISTER_ISR_HANDLER(1);
|
ISR_LIST_X
|
||||||
REGISTER_ISR_HANDLER(2);
|
#undef X
|
||||||
REGISTER_ISR_HANDLER(3);
|
|
||||||
REGISTER_ISR_HANDLER(4);
|
|
||||||
REGISTER_ISR_HANDLER(5);
|
|
||||||
REGISTER_ISR_HANDLER(6);
|
|
||||||
REGISTER_ISR_HANDLER(7);
|
|
||||||
REGISTER_ISR_HANDLER(8);
|
|
||||||
REGISTER_ISR_HANDLER(9);
|
|
||||||
REGISTER_ISR_HANDLER(10);
|
|
||||||
REGISTER_ISR_HANDLER(11);
|
|
||||||
REGISTER_ISR_HANDLER(12);
|
|
||||||
REGISTER_ISR_HANDLER(13);
|
|
||||||
REGISTER_ISR_HANDLER(14);
|
|
||||||
REGISTER_ISR_HANDLER(15);
|
|
||||||
REGISTER_ISR_HANDLER(16);
|
|
||||||
REGISTER_ISR_HANDLER(17);
|
|
||||||
REGISTER_ISR_HANDLER(18);
|
|
||||||
REGISTER_ISR_HANDLER(19);
|
|
||||||
REGISTER_ISR_HANDLER(20);
|
|
||||||
REGISTER_ISR_HANDLER(21);
|
|
||||||
REGISTER_ISR_HANDLER(22);
|
|
||||||
REGISTER_ISR_HANDLER(23);
|
|
||||||
REGISTER_ISR_HANDLER(24);
|
|
||||||
REGISTER_ISR_HANDLER(25);
|
|
||||||
REGISTER_ISR_HANDLER(26);
|
|
||||||
REGISTER_ISR_HANDLER(27);
|
|
||||||
REGISTER_ISR_HANDLER(28);
|
|
||||||
REGISTER_ISR_HANDLER(29);
|
|
||||||
REGISTER_ISR_HANDLER(30);
|
|
||||||
REGISTER_ISR_HANDLER(31);
|
|
||||||
|
|
||||||
REGISTER_IRQ_HANDLER(0);
|
#define X(num) register_interrupt_handler(IRQ_VECTOR_BASE + num, irq ## num);
|
||||||
REGISTER_IRQ_HANDLER(1);
|
IRQ_LIST_X
|
||||||
REGISTER_IRQ_HANDLER(2);
|
#undef X
|
||||||
REGISTER_IRQ_HANDLER(3);
|
|
||||||
REGISTER_IRQ_HANDLER(4);
|
|
||||||
REGISTER_IRQ_HANDLER(5);
|
|
||||||
REGISTER_IRQ_HANDLER(6);
|
|
||||||
REGISTER_IRQ_HANDLER(7);
|
|
||||||
REGISTER_IRQ_HANDLER(8);
|
|
||||||
REGISTER_IRQ_HANDLER(9);
|
|
||||||
REGISTER_IRQ_HANDLER(10);
|
|
||||||
REGISTER_IRQ_HANDLER(11);
|
|
||||||
REGISTER_IRQ_HANDLER(12);
|
|
||||||
REGISTER_IRQ_HANDLER(13);
|
|
||||||
REGISTER_IRQ_HANDLER(14);
|
|
||||||
REGISTER_IRQ_HANDLER(15);
|
|
||||||
|
|
||||||
register_syscall_handler(0x80, syscall_asm);
|
register_syscall_handler(0x80, syscall_asm);
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,22 @@ irq 12
|
||||||
irq 13
|
irq 13
|
||||||
irq 14
|
irq 14
|
||||||
irq 15
|
irq 15
|
||||||
|
irq 16
|
||||||
|
irq 17
|
||||||
|
irq 18
|
||||||
|
irq 19
|
||||||
|
irq 20
|
||||||
|
irq 21
|
||||||
|
irq 22
|
||||||
|
irq 23
|
||||||
|
irq 24
|
||||||
|
irq 25
|
||||||
|
irq 26
|
||||||
|
irq 27
|
||||||
|
irq 28
|
||||||
|
irq 29
|
||||||
|
irq 30
|
||||||
|
irq 31
|
||||||
|
|
||||||
// arguments in RAX, RBX, RCX, RDX, RSI, RDI
|
// arguments in RAX, RBX, RCX, RDX, RSI, RDI
|
||||||
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
|
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
|
||||||
|
|
|
@ -108,7 +108,7 @@ namespace Kernel
|
||||||
static BAN::ErrorOr<void> initialize();
|
static BAN::ErrorOr<void> initialize();
|
||||||
static ACPI& get();
|
static ACPI& get();
|
||||||
|
|
||||||
const SDTHeader* get_header(const char[4]);
|
const SDTHeader* get_header(BAN::StringView signature, uint32_t index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ACPI() = default;
|
ACPI() = default;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define ALWAYS_INLINE inline __attribute__((always_inline))
|
#define ALWAYS_INLINE inline __attribute__((always_inline))
|
||||||
|
#define NEVER_INLINE __attribute__((noinline))
|
||||||
|
|
|
@ -11,14 +11,16 @@ namespace Kernel
|
||||||
class Interruptable
|
class Interruptable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Interruptable() = default;
|
|
||||||
|
|
||||||
void set_irq(int irq);
|
void set_irq(int irq);
|
||||||
void enable_interrupt();
|
void enable_interrupt();
|
||||||
void disable_interrupt();
|
void disable_interrupt();
|
||||||
|
|
||||||
virtual void handle_irq() = 0;
|
virtual void handle_irq() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Interruptable() = default;
|
||||||
|
~Interruptable() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_irq { -1 };
|
int m_irq { -1 };
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace Kernel
|
||||||
class E1000 final : public NetworkDriver
|
class E1000 final : public NetworkDriver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static bool probe(PCI::Device&);
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<E1000>> create(PCI::Device&);
|
static BAN::ErrorOr<BAN::UniqPtr<E1000>> create(PCI::Device&);
|
||||||
~E1000();
|
~E1000();
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,9 @@ namespace Kernel::PCI
|
||||||
|
|
||||||
uint8_t header_type() const { return m_header_type; }
|
uint8_t header_type() const { return m_header_type; }
|
||||||
|
|
||||||
|
uint16_t vendor_id() const { return m_vendor_id; }
|
||||||
|
uint16_t device_id() const { return m_device_id; }
|
||||||
|
|
||||||
BAN::ErrorOr<uint8_t> get_irq();
|
BAN::ErrorOr<uint8_t> get_irq();
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<BarRegion>> allocate_bar_region(uint8_t bar_num);
|
BAN::ErrorOr<BAN::UniqPtr<BarRegion>> allocate_bar_region(uint8_t bar_num);
|
||||||
|
@ -107,6 +110,8 @@ namespace Kernel::PCI
|
||||||
uint8_t m_prog_if;
|
uint8_t m_prog_if;
|
||||||
|
|
||||||
uint8_t m_header_type;
|
uint8_t m_header_type;
|
||||||
|
uint16_t m_vendor_id;
|
||||||
|
uint16_t m_device_id;
|
||||||
|
|
||||||
BAN::Optional<uint8_t> m_offset_msi;
|
BAN::Optional<uint8_t> m_offset_msi;
|
||||||
BAN::Optional<uint8_t> m_offset_msi_x;
|
BAN::Optional<uint8_t> m_offset_msi_x;
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace Kernel
|
||||||
static bool is_valid_tid(pid_t tid);
|
static bool is_valid_tid(pid_t tid);
|
||||||
|
|
||||||
[[noreturn]] void execute_current_thread();
|
[[noreturn]] void execute_current_thread();
|
||||||
|
[[noreturn]] void _execute_current_thread();
|
||||||
[[noreturn]] void delete_current_process_and_thread();
|
[[noreturn]] void delete_current_process_and_thread();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace Kernel
|
||||||
|
|
||||||
virtual uint32_t width() const override;
|
virtual uint32_t width() const override;
|
||||||
virtual uint32_t height() const override;
|
virtual uint32_t height() const override;
|
||||||
virtual void putchar_impl(uint8_t) override;
|
|
||||||
|
virtual void clear() override { putchar_impl('\e'); putchar_impl('['); putchar_impl('2'); putchar_impl('J'); }
|
||||||
|
|
||||||
virtual void update() override;
|
virtual void update() override;
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@ namespace Kernel
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual BAN::StringView name() const override { return m_name; }
|
virtual BAN::StringView name() const override { return m_name; }
|
||||||
|
virtual void putchar_impl(uint8_t) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SerialTTY(Serial);
|
SerialTTY(Serial);
|
||||||
|
|
|
@ -38,7 +38,8 @@ namespace Kernel
|
||||||
virtual uint32_t height() const = 0;
|
virtual uint32_t height() const = 0;
|
||||||
virtual uint32_t width() const = 0;
|
virtual uint32_t width() const = 0;
|
||||||
void putchar(uint8_t ch);
|
void putchar(uint8_t ch);
|
||||||
virtual void putchar_impl(uint8_t ch) = 0;
|
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
virtual bool has_data_impl() const override;
|
virtual bool has_data_impl() const override;
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ namespace Kernel
|
||||||
: CharacterDevice(mode, uid, gid)
|
: CharacterDevice(mode, uid, gid)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
virtual void putchar_impl(uint8_t ch) = 0;
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
||||||
|
|
||||||
|
|
|
@ -21,15 +21,16 @@ namespace Kernel
|
||||||
|
|
||||||
virtual uint32_t height() const override { return m_height; }
|
virtual uint32_t height() const override { return m_height; }
|
||||||
virtual uint32_t width() const override { return m_width; }
|
virtual uint32_t width() const override { return m_width; }
|
||||||
virtual void putchar_impl(uint8_t ch) override;
|
|
||||||
|
virtual void clear() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual BAN::StringView name() const override { return m_name; }
|
virtual BAN::StringView name() const override { return m_name; }
|
||||||
|
virtual void putchar_impl(uint8_t ch) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VirtualTTY(TerminalDriver*);
|
VirtualTTY(TerminalDriver*);
|
||||||
|
|
||||||
void clear();
|
|
||||||
void reset_ansi();
|
void reset_ansi();
|
||||||
void handle_ansi_csi(uint8_t ch);
|
void handle_ansi_csi(uint8_t ch);
|
||||||
void handle_ansi_csi_color();
|
void handle_ansi_csi_color();
|
||||||
|
|
|
@ -222,13 +222,20 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const ACPI::SDTHeader* ACPI::get_header(const char signature[4])
|
const ACPI::SDTHeader* ACPI::get_header(BAN::StringView signature, uint32_t index)
|
||||||
{
|
{
|
||||||
|
if (signature.size() != 4)
|
||||||
|
{
|
||||||
|
dprintln("Trying to get ACPI header with {} byte signature ??", signature.size());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
uint32_t cnt = 0;
|
||||||
for (auto& mapped_header : m_mapped_headers)
|
for (auto& mapped_header : m_mapped_headers)
|
||||||
{
|
{
|
||||||
auto* header = mapped_header.as_header();
|
auto* header = mapped_header.as_header();
|
||||||
if (memcmp(header->signature, signature, 4) == 0)
|
if (memcmp(header->signature, signature.data(), 4) == 0)
|
||||||
return header;
|
if (cnt++ == index)
|
||||||
|
return header;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ namespace Kernel
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MADT* madt = (const MADT*)Kernel::ACPI::get().get_header("APIC");
|
const MADT* madt = (const MADT*)Kernel::ACPI::get().get_header("APIC"sv, 0);
|
||||||
if (madt == nullptr)
|
if (madt == nullptr)
|
||||||
{
|
{
|
||||||
dprintln("Could not find MADT header");
|
dprintln("Could not find MADT header");
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
#include <kernel/Terminal/TTY.h>
|
#include <kernel/Terminal/TTY.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
extern TerminalDriver* g_terminal_driver;
|
||||||
|
|
||||||
namespace Debug
|
namespace Debug
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -64,6 +68,50 @@ namespace Debug
|
||||||
return Kernel::Serial::putchar_any(ch);
|
return Kernel::Serial::putchar_any(ch);
|
||||||
if (Kernel::TTY::is_initialized())
|
if (Kernel::TTY::is_initialized())
|
||||||
return Kernel::TTY::putchar_current(ch);
|
return Kernel::TTY::putchar_current(ch);
|
||||||
|
|
||||||
|
if (g_terminal_driver)
|
||||||
|
{
|
||||||
|
static uint32_t col = 0;
|
||||||
|
static uint32_t row = 0;
|
||||||
|
|
||||||
|
uint32_t row_copy = row;
|
||||||
|
|
||||||
|
if (ch == '\n')
|
||||||
|
{
|
||||||
|
row++;
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
else if (ch == '\r')
|
||||||
|
{
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!isprint(ch))
|
||||||
|
ch = '?';
|
||||||
|
g_terminal_driver->putchar_at(ch, col, row, TerminalColor::BRIGHT_WHITE, TerminalColor::BLACK);
|
||||||
|
|
||||||
|
col++;
|
||||||
|
if (col >= g_terminal_driver->width())
|
||||||
|
{
|
||||||
|
row++;
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row >= g_terminal_driver->height())
|
||||||
|
row = 0;
|
||||||
|
|
||||||
|
if (row != row_copy)
|
||||||
|
{
|
||||||
|
for (uint32_t i = col; i < g_terminal_driver->width(); i++)
|
||||||
|
{
|
||||||
|
g_terminal_driver->putchar_at(' ', i, row, TerminalColor::BRIGHT_WHITE, TerminalColor::BLACK);
|
||||||
|
if (row + 1 < g_terminal_driver->height())
|
||||||
|
g_terminal_driver->putchar_at(' ', i, row + 1, TerminalColor::BRIGHT_WHITE, TerminalColor::BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_prefix(const char* file, int line)
|
void print_prefix(const char* file, int line)
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Kernel
|
||||||
|
|
||||||
m_vaddr = PageTable::kernel().reserve_free_contiguous_pages(m_bitmap_pages, KERNEL_OFFSET);
|
m_vaddr = PageTable::kernel().reserve_free_contiguous_pages(m_bitmap_pages, KERNEL_OFFSET);
|
||||||
ASSERT(m_vaddr);
|
ASSERT(m_vaddr);
|
||||||
PageTable::kernel().map_range_at(m_paddr, m_vaddr, size, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
PageTable::kernel().map_range_at(m_paddr, m_vaddr, m_bitmap_pages * PAGE_SIZE, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||||
|
|
||||||
memset((void*)m_vaddr, 0x00, m_bitmap_pages * PAGE_SIZE);
|
memset((void*)m_vaddr, 0x00, m_bitmap_pages * PAGE_SIZE);
|
||||||
|
|
||||||
|
@ -36,8 +36,6 @@ namespace Kernel
|
||||||
ull bits = m_data_pages % ull_bits;
|
ull bits = m_data_pages % ull_bits;
|
||||||
ull_bitmap_ptr()[off] = ~(~0ull << bits);
|
ull_bitmap_ptr()[off] = ~(~0ull << bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintln("physical range needs {} pages for bitmap", m_bitmap_pages);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
paddr_t PhysicalRange::paddr_for_bit(ull bit) const
|
paddr_t PhysicalRange::paddr_for_bit(ull bit) const
|
||||||
|
|
|
@ -112,6 +112,45 @@ namespace Kernel
|
||||||
volatile uint16_t special;
|
volatile uint16_t special;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
// https://www.intel.com/content/dam/doc/manual/pci-pci-x-family-gbe-controllers-software-dev-manual.pdf (section 5.2)
|
||||||
|
bool E1000::probe(PCI::Device& pci_device)
|
||||||
|
{
|
||||||
|
// Intel device
|
||||||
|
if (pci_device.vendor_id() != 0x8086)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (pci_device.device_id())
|
||||||
|
{
|
||||||
|
case 0x1019:
|
||||||
|
case 0x101A:
|
||||||
|
case 0x1010:
|
||||||
|
case 0x1012:
|
||||||
|
case 0x101D:
|
||||||
|
case 0x1079:
|
||||||
|
case 0x107A:
|
||||||
|
case 0x107B:
|
||||||
|
case 0x100F:
|
||||||
|
case 0x1011:
|
||||||
|
case 0x1026:
|
||||||
|
case 0x1027:
|
||||||
|
case 0x1028:
|
||||||
|
case 0x1107:
|
||||||
|
case 0x1112:
|
||||||
|
case 0x1013:
|
||||||
|
case 0x1018:
|
||||||
|
case 0x1076:
|
||||||
|
case 0x1077:
|
||||||
|
case 0x1078:
|
||||||
|
case 0x1017:
|
||||||
|
case 0x1016:
|
||||||
|
case 0x100e:
|
||||||
|
case 0x1015:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<E1000>> E1000::create(PCI::Device& pci_device)
|
BAN::ErrorOr<BAN::UniqPtr<E1000>> E1000::create(PCI::Device& pci_device)
|
||||||
{
|
{
|
||||||
E1000* e1000 = new E1000();
|
E1000* e1000 = new E1000();
|
||||||
|
|
|
@ -173,8 +173,9 @@ namespace Kernel::PCI
|
||||||
switch (pci_device.subclass())
|
switch (pci_device.subclass())
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0x00:
|
||||||
if (auto res = E1000::create(pci_device); res.is_error())
|
if (E1000::probe(pci_device))
|
||||||
dprintln("E1000: {}", res.error());
|
if (auto res = E1000::create(pci_device); res.is_error())
|
||||||
|
dprintln("E1000: {}", res.error());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dprintln("unsupported ethernet device (pci {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if());
|
dprintln("unsupported ethernet device (pci {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if());
|
||||||
|
@ -190,7 +191,11 @@ namespace Kernel::PCI
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<BarRegion>> BarRegion::create(PCI::Device& device, uint8_t bar_num)
|
BAN::ErrorOr<BAN::UniqPtr<BarRegion>> BarRegion::create(PCI::Device& device, uint8_t bar_num)
|
||||||
{
|
{
|
||||||
ASSERT(device.header_type() == 0x00);
|
if (device.header_type() != 0x00)
|
||||||
|
{
|
||||||
|
dprintln("BAR regions for non general devices are not supported");
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
// disable io/mem space while reading bar
|
// disable io/mem space while reading bar
|
||||||
uint16_t command = device.read_word(PCI_REG_COMMAND);
|
uint16_t command = device.read_word(PCI_REG_COMMAND);
|
||||||
|
@ -333,6 +338,15 @@ namespace Kernel::PCI
|
||||||
m_prog_if = read_byte(0x09);
|
m_prog_if = read_byte(0x09);
|
||||||
m_header_type = read_byte(0x0E);
|
m_header_type = read_byte(0x0E);
|
||||||
|
|
||||||
|
uint32_t device = read_dword(0x00);
|
||||||
|
m_vendor_id = device & 0xFFFF;
|
||||||
|
m_device_id = device >> 16;
|
||||||
|
|
||||||
|
dprintln("PCI {2H}:{2H}.{2H} has {2H}.{2H}.{2H}",
|
||||||
|
m_bus, m_dev, m_func,
|
||||||
|
m_class_code, m_subclass, m_prog_if
|
||||||
|
);
|
||||||
|
|
||||||
enumerate_capabilites();
|
enumerate_capabilites();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,11 +404,9 @@ namespace Kernel::PCI
|
||||||
{
|
{
|
||||||
case 0x05:
|
case 0x05:
|
||||||
m_offset_msi = capability_offset;
|
m_offset_msi = capability_offset;
|
||||||
dprintln("{}:{}.{} has MSI", m_bus, m_dev, m_func);
|
|
||||||
break;
|
break;
|
||||||
case 0x11:
|
case 0x11:
|
||||||
m_offset_msi_x = capability_offset;
|
m_offset_msi_x = capability_offset;
|
||||||
dprintln("{}:{}.{} has MSI-X", m_bus, m_dev, m_func);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -123,6 +123,11 @@ namespace Kernel
|
||||||
TRY(process->m_cmdline.back().append(path));
|
TRY(process->m_cmdline.back().append(path));
|
||||||
|
|
||||||
process->m_loadable_elf = TRY(load_elf_for_exec(credentials, path, "/"sv, process->page_table()));
|
process->m_loadable_elf = TRY(load_elf_for_exec(credentials, path, "/"sv, process->page_table()));
|
||||||
|
if (!process->m_loadable_elf->is_address_space_free())
|
||||||
|
{
|
||||||
|
dprintln("Could not load ELF address space");
|
||||||
|
return BAN::Error::from_errno(ENOEXEC);
|
||||||
|
}
|
||||||
process->m_loadable_elf->reserve_address_space();
|
process->m_loadable_elf->reserve_address_space();
|
||||||
|
|
||||||
process->m_is_userspace = true;
|
process->m_is_userspace = true;
|
||||||
|
@ -460,6 +465,11 @@ namespace Kernel
|
||||||
m_loadable_elf.clear();
|
m_loadable_elf.clear();
|
||||||
|
|
||||||
m_loadable_elf = TRY(load_elf_for_exec(m_credentials, executable_path, m_working_directory, page_table()));
|
m_loadable_elf = TRY(load_elf_for_exec(m_credentials, executable_path, m_working_directory, page_table()));
|
||||||
|
if (!m_loadable_elf->is_address_space_free())
|
||||||
|
{
|
||||||
|
dprintln("ELF has unloadable address space");
|
||||||
|
MUST(sys_raise(SIGKILL));
|
||||||
|
}
|
||||||
m_loadable_elf->reserve_address_space();
|
m_loadable_elf->reserve_address_space();
|
||||||
m_userspace_info.entry = m_loadable_elf->entry_point();
|
m_userspace_info.entry = m_loadable_elf->entry_point();
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Timer/PIT.h>
|
#include <kernel/Timer/PIT.h>
|
||||||
|
|
||||||
#if 1
|
#define SCHEDULER_VERIFY_STACK 1
|
||||||
|
#define SCHEDULER_VERIFY_INTERRUPT_STATE 1
|
||||||
|
|
||||||
|
#if SCHEDULER_VERIFY_INTERRUPT_STATE
|
||||||
#define VERIFY_STI() ASSERT(interrupts_enabled())
|
#define VERIFY_STI() ASSERT(interrupts_enabled())
|
||||||
#define VERIFY_CLI() ASSERT(!interrupts_enabled())
|
#define VERIFY_CLI() ASSERT(!interrupts_enabled())
|
||||||
#else
|
#else
|
||||||
|
@ -202,6 +205,7 @@ namespace Kernel
|
||||||
delete thread;
|
delete thread;
|
||||||
|
|
||||||
execute_current_thread();
|
execute_current_thread();
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::execute_current_thread()
|
void Scheduler::execute_current_thread()
|
||||||
|
@ -210,6 +214,20 @@ namespace Kernel
|
||||||
|
|
||||||
load_temp_stack();
|
load_temp_stack();
|
||||||
PageTable::kernel().load();
|
PageTable::kernel().load();
|
||||||
|
_execute_current_thread();
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
NEVER_INLINE void Scheduler::_execute_current_thread()
|
||||||
|
{
|
||||||
|
VERIFY_CLI();
|
||||||
|
|
||||||
|
#if SCHEDULER_VERIFY_STACK
|
||||||
|
vaddr_t rsp;
|
||||||
|
read_rsp(rsp);
|
||||||
|
ASSERT((vaddr_t)s_temp_stack <= rsp && rsp <= (vaddr_t)s_temp_stack + sizeof(s_temp_stack));
|
||||||
|
ASSERT(&PageTable::current() == &PageTable::kernel());
|
||||||
|
#endif
|
||||||
|
|
||||||
Thread* current = ¤t_thread();
|
Thread* current = ¤t_thread();
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace Kernel
|
||||||
void TTY::set_as_current()
|
void TTY::set_as_current()
|
||||||
{
|
{
|
||||||
s_tty = this;
|
s_tty = this;
|
||||||
|
clear();
|
||||||
|
|
||||||
auto inode_or_error = DevFileSystem::get().root_inode()->find_inode("tty"sv);
|
auto inode_or_error = DevFileSystem::get().root_inode()->find_inode("tty"sv);
|
||||||
if (inode_or_error.is_error())
|
if (inode_or_error.is_error())
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> HPET::initialize(bool force_pic)
|
BAN::ErrorOr<void> HPET::initialize(bool force_pic)
|
||||||
{
|
{
|
||||||
auto* header = (ACPI::HPET*)ACPI::get().get_header("HPET");
|
auto* header = (ACPI::HPET*)ACPI::get().get_header("HPET"sv, 0);
|
||||||
if (header == nullptr)
|
if (header == nullptr)
|
||||||
return BAN::Error::from_errno(ENODEV);
|
return BAN::Error::from_errno(ENODEV);
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,8 @@ static void parse_command_line()
|
||||||
extern "C" uint8_t g_userspace_start[];
|
extern "C" uint8_t g_userspace_start[];
|
||||||
extern "C" uint8_t g_userspace_end[];
|
extern "C" uint8_t g_userspace_end[];
|
||||||
|
|
||||||
|
TerminalDriver* g_terminal_driver = nullptr;
|
||||||
|
|
||||||
static void init2(void*);
|
static void init2(void*);
|
||||||
|
|
||||||
extern "C" void kernel_main()
|
extern "C" void kernel_main()
|
||||||
|
@ -114,6 +116,10 @@ extern "C" void kernel_main()
|
||||||
PageTable::initialize();
|
PageTable::initialize();
|
||||||
dprintln("PageTable initialized");
|
dprintln("PageTable initialized");
|
||||||
|
|
||||||
|
g_terminal_driver = VesaTerminalDriver::create();
|
||||||
|
if (g_terminal_driver)
|
||||||
|
dprintln("VESA initialized");
|
||||||
|
|
||||||
Heap::initialize();
|
Heap::initialize();
|
||||||
dprintln("Heap initialzed");
|
dprintln("Heap initialzed");
|
||||||
|
|
||||||
|
@ -141,12 +147,11 @@ extern "C" void kernel_main()
|
||||||
dprintln("Serial devices initialized");
|
dprintln("Serial devices initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminalDriver* terminal_driver = VesaTerminalDriver::create();
|
if (g_terminal_driver)
|
||||||
ASSERT(terminal_driver);
|
{
|
||||||
dprintln("VESA initialized");
|
auto vtty = MUST(VirtualTTY::create(g_terminal_driver));
|
||||||
|
dprintln("Virtual TTY initialized");
|
||||||
auto vtty = MUST(VirtualTTY::create(terminal_driver));
|
}
|
||||||
dprintln("Virtual TTY initialized");
|
|
||||||
|
|
||||||
MUST(Scheduler::initialize());
|
MUST(Scheduler::initialize());
|
||||||
dprintln("Scheduler initialized");
|
dprintln("Scheduler initialized");
|
||||||
|
|
|
@ -51,8 +51,7 @@ void laihost_panic(const char* msg)
|
||||||
|
|
||||||
void* laihost_scan(const char* sig, size_t index)
|
void* laihost_scan(const char* sig, size_t index)
|
||||||
{
|
{
|
||||||
ASSERT(index == 0);
|
return (void*)ACPI::get().get_header(sig, index);
|
||||||
return (void*)ACPI::get().get_header(sig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* laihost_map(size_t address, size_t count)
|
void* laihost_map(size_t address, size_t count)
|
||||||
|
|
9
qemu.sh
9
qemu.sh
|
@ -1,9 +1,18 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
if [ -z ${OVMF_PATH+x} ]; then
|
||||||
|
OVMF_PATH="/usr/share/ovmf/x64/OVMF.fd"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$UEFI_BOOT" == "1" ]; then
|
||||||
|
BIOS_ARGS="-bios $OVMF_PATH -net none"
|
||||||
|
fi
|
||||||
|
|
||||||
qemu-system-$BANAN_ARCH \
|
qemu-system-$BANAN_ARCH \
|
||||||
-m 128 \
|
-m 128 \
|
||||||
-smp 2 \
|
-smp 2 \
|
||||||
|
$BIOS_ARGS \
|
||||||
-drive format=raw,id=disk,file=${DISK_IMAGE_PATH},if=none \
|
-drive format=raw,id=disk,file=${DISK_IMAGE_PATH},if=none \
|
||||||
-device ahci,id=ahci \
|
-device ahci,id=ahci \
|
||||||
-device ide-hd,drive=disk,bus=ahci.0 \
|
-device ide-hd,drive=disk,bus=ahci.0 \
|
||||||
|
|
|
@ -3,6 +3,7 @@ set -e
|
||||||
|
|
||||||
BINUTILS_VERSION="binutils-2.39"
|
BINUTILS_VERSION="binutils-2.39"
|
||||||
GCC_VERSION="gcc-12.2.0"
|
GCC_VERSION="gcc-12.2.0"
|
||||||
|
GRUB_VERSION="grub-2.06"
|
||||||
|
|
||||||
cd $(dirname "$0")
|
cd $(dirname "$0")
|
||||||
|
|
||||||
|
@ -74,7 +75,7 @@ if [ ! -f ${PREFIX}/bin/${TARGET}-g++ ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p build/${GCC_VERSION}/
|
mkdir -p build/${GCC_VERSION}/
|
||||||
cd build/${GCC_VERSION}/
|
pushd build/${GCC_VERSION}/
|
||||||
|
|
||||||
../../${GCC_VERSION}/configure \
|
../../${GCC_VERSION}/configure \
|
||||||
--target="$TARGET" \
|
--target="$TARGET" \
|
||||||
|
@ -87,4 +88,34 @@ if [ ! -f ${PREFIX}/bin/${TARGET}-g++ ]; then
|
||||||
make -j $(nproc) all-target-libgcc CFLAGS_FOR_TARGET='-g -O2 -mcmodel=large -mno-red-zone'
|
make -j $(nproc) all-target-libgcc CFLAGS_FOR_TARGET='-g -O2 -mcmodel=large -mno-red-zone'
|
||||||
make install-gcc install-target-libgcc
|
make install-gcc install-target-libgcc
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f ${PREFIX}/bin/grub-mkstandalone ]; then
|
||||||
|
|
||||||
|
echo "Building ${GRUB_VERSION}"
|
||||||
|
|
||||||
|
if [ ! -f ${GRUB_VERSION}.tar.xz ]; then
|
||||||
|
wget https://ftp.gnu.org/gnu/grub/${GRUB_VERSION}.tar.xz
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d $GRUB_VERSION ]; then
|
||||||
|
tar xvf ${GRUB_VERSION}.tar.xz
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p build/${GRUB_VERSION}/
|
||||||
|
pushd build/${GRUB_VERSION}/
|
||||||
|
|
||||||
|
../../${GRUB_VERSION}/configure \
|
||||||
|
--target="$ARCH" \
|
||||||
|
--prefix="$PREFIX" \
|
||||||
|
--with-platform="efi" \
|
||||||
|
--disable-werror
|
||||||
|
|
||||||
|
make -j $(nproc)
|
||||||
|
make install
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
menuentry "banan-os" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "banan-os (no serial)" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2 noserial
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "banan-os (only serial)" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2 console=ttyS0
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "banan-os (no apic)" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "banan-os (no apic, no serial)" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic noserial
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "banan-os (no apic, only serial)" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic console=ttyS0
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
insmod part_gpt
|
||||||
|
configfile (hd0,gpt2)/boot/grub/grub.cfg
|
|
@ -0,0 +1,26 @@
|
||||||
|
insmod part_gpt
|
||||||
|
set root=(hd0,gpt2)
|
||||||
|
|
||||||
|
menuentry "banan-os" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "banan-os (no serial)" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2 noserial
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "banan-os (only serial)" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2 console=ttyS0
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "banan-os (no apic)" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "banan-os (no apic, no serial)" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic noserial
|
||||||
|
}
|
||||||
|
|
||||||
|
menuentry "banan-os (no apic, only serial)" {
|
||||||
|
multiboot /boot/banan-os.kernel root=/dev/sda2 noapic console=ttyS0
|
||||||
|
}
|
|
@ -156,7 +156,9 @@ BAN::Optional<BAN::String> parse_dollar(BAN::StringView command, size_t& i)
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "$"sv;
|
BAN::String temp = "$"sv;
|
||||||
|
MUST(temp.push_back(command[i]));
|
||||||
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::StringView strip_whitespace(BAN::StringView sv)
|
BAN::StringView strip_whitespace(BAN::StringView sv)
|
||||||
|
|
Loading…
Reference in New Issue