WIP: paging and better malloc.

This commit is contained in:
Patrick 2024-01-26 15:02:30 +01:00
parent 75ec3751fe
commit 836d589c9b
19 changed files with 1230 additions and 56 deletions

View File

@ -15,6 +15,7 @@ target = GetOption('target')
env = Environment(tools = ['default', 'compilation_db'])
env.Append(CCFLAGS = ['-g', '-O0'])
env.Append(CPPDEFINES = ['BASTL_EXTENSIONS=1'])
# env.Append(CCFLAGS = ['-O2'])
env['ISO_FILES'] = []

View File

@ -4,6 +4,10 @@
#if !defined(BAD_APPLE_OS_ALGORITHM_INCLUDED)
#define BAD_APPLE_OS_ALGORITHM_INCLUDED
#include <cstddef>
#include <iterator>
#include <utility>
namespace std
{
template<typename T>
@ -17,6 +21,76 @@ constexpr const T& max(const T& left, const T& right)
{
return right > left ? right : left;
}
template<typename RandomIt, class Compare>
constexpr void sort(RandomIt first, RandomIt last, Compare comp)
{
// TODO: be smarter
const size_t size = last - first;
size_t sorted = 1;
while (sorted < size)
{
// find insertion pos
size_t pos = 0;
while (pos < sorted)
{
if (comp(*(first + sorted), *(first + pos)))
{
break;
}
++pos;
}
// bail if already sorted
if (pos == sorted)
{
++sorted;
continue;
}
// insert at pos
for (size_t idx = pos; idx < sorted; ++idx)
{
swap(*(first + idx), *(first + sorted));
}
++sorted;
}
}
template<typename RandomIt>
constexpr void sort(RandomIt first, RandomIt last)
{
sort(first, last, [](auto left, auto right) { return left < right; });
}
template<typename ForwardIt, typename UnaryPredicate>
constexpr ForwardIt find_if(ForwardIt first, ForwardIt last, UnaryPredicate pred)
{
for (auto it = first; it != last; ++it)
{
if (pred(*it))
{
return it;
}
}
return last;
}
template<typename ForwardIt, typename UnaryPredicate>
constexpr ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate pred)
{
auto found = find_if(first, last, pred);
if (found != last)
{
for (auto tomove = next(found); tomove != last; ++tomove)
{
if (!pred(*tomove))
{
*found = move(*tomove);
++found;
}
}
}
return found;
}
}
#endif // !defined(BAD_APPLE_OS_ALGORITHM_INCLUDED)

18
bastl/include/iterator Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#if !defined(BAD_APPLE_OS_ITERATOR_HPP_INCLUDED)
#define BAD_APPLE_OS_ITERATOR_HPP_INCLUDED
#include <cstddef>
namespace std
{
template<typename InputIt>
InputIt next(InputIt it, std::ptrdiff_t n = 1) // TODO: this is not really correct...
{
return it + n;
}
}
#endif // !defined(BAD_APPLE_OS_ITERATOR_HPP_INCLUDED)

44
bastl/include/memory Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#if !defined(BAD_APPLE_OS_MEMORY_HPP_INCLUDED)
#define BAD_APPLE_OS_MEMORY_HPP_INCLUDED
#include <cstddef>
namespace std
{
constexpr void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space) noexcept
{
if (space < size) {
return nullptr;
}
std::size_t addr = __builtin_bit_cast(std::size_t, ptr);
if (addr % alignment != 0)
{
std::size_t offset = alignment + (addr % alignment);
if (space < size + offset)
{
return nullptr;
}
addr += offset;
space -= offset;
ptr = __builtin_bit_cast(void*, addr);
}
return ptr;
}
#if defined(BASTL_EXTENSIONS)
template<typename T>
constexpr T alignUp(T value, T alignTo) noexcept
{
if (value % alignTo != 0)
{
return value + alignTo - (value % alignTo);
}
return value;
}
#endif
}
#endif // !defined(BAD_APPLE_OS_MEMORY_HPP_INCLUDED)

93
bastl/include/span Normal file
View File

@ -0,0 +1,93 @@
#pragma once
#if !defined(BAD_APPLE_OS_SPAN_HPP_INCLUDED)
#define BAD_APPLE_OS_SPAN_HPP_INCLUDED
#include <array>
#include <cstddef>
#include <initializer_list>
#include <stdexcept>
#include <type_traits>
namespace std
{
inline constexpr size_t dynamic_extent = size_t(-1);
template<typename T, size_t Extent = dynamic_extent> // TODO: use the extent?
class span
{
public:
using element_type = T;
using value_type = remove_cv_t<T>;
using size_type = size_t;
using difference_type = ptrdiff_t;
using reference = element_type&;
using const_reference = const element_type&;
using pointer = element_type*;
using const_pointer = const element_type*;
using iterator = pointer;
using const_iterator = const_pointer;
static constexpr size_t extent = Extent;
private:
pointer _first = nullptr;
pointer _last = nullptr;
public:
constexpr span() noexcept = default;
constexpr span(const span&) noexcept = default;
template<typename It>
explicit(extent != dynamic_extent)
constexpr span(It first, size_type count) : _first(&*first), _last(&*(_first + count)) {}
template<typename It>
explicit(extent != dynamic_extent)
constexpr span(It first, It last) : _first(&*first), _last(&*last) {}
template<size_t N>
constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept : span(&arr[0], N) {}
template<typename U, size_t N>
constexpr span(array<U, N>& arr) noexcept : span(&arr[0], N) {}
template<typename U, size_t N>
constexpr span(const array<U, N>& arr) noexcept : span(&arr[0], N) {}
explicit(Extent != dynamic_extent)
constexpr span(initializer_list<value_type> il) noexcept : span(il.begin(), il.size()) {}
template<typename U, size_t N>
explicit(extent != dynamic_extent && N != dynamic_extent)
constexpr span(const span<U, N>& source) noexcept : span(source.begin(), source.end()) {}
constexpr span& operator=(const span&) noexcept = default;
constexpr reference operator[](size_type idx) const { return _first[idx]; }
constexpr iterator begin() const noexcept { return _first; }
constexpr const_iterator cbegin() const noexcept { return _first; }
constexpr iterator end() const noexcept { return _last; }
constexpr const_iterator cend() const noexcept { return _last; }
constexpr reference front() const { return *_first; }
constexpr reference back() const { return *(_last - 1); }
constexpr reference at(size_type pos) const
{
if (pos >= size()) {
__ba_throw std::out_of_range();
}
return (*this)[pos];
}
constexpr pointer data() const noexcept { return _first; }
constexpr size_type size() const noexcept { return _last - _first; }
constexpr size_type size_bytes() const noexcept { return size() * sizeof(element_type); }
constexpr bool empty() const noexcept { return size() == 0; }
// TODO: subspans
};
}
#endif // !defined(BAD_APPLE_OS_SPAN_HPP_INCLUDED)

View File

@ -26,6 +26,66 @@ struct remove_reference<T&&>
template<typename T>
using remove_reference_t = typename remove_reference<T>::type;
template<typename T>
struct remove_const
{
using type = T;
};
template<typename T>
struct remove_const<const T>
{
using type = T;
};
template<typename T>
using remove_const_t = typename remove_const<T>::type;
template<typename T>
struct remove_volatile
{
using type = T;
};
template<typename T>
struct remove_volatile<volatile T>
{
using type = T;
};
template<typename T>
using remove_volatile_t = typename remove_volatile<T>::type;
template<typename T>
struct remove_cv
{
using type = T;
};
template<typename T>
struct remove_cv<const T>
{
using type = T;
};
template<typename T>
struct remove_cv<const volatile T>
{
using type = T;
};
template<typename T>
using remove_cv_t = typename remove_cv<T>::type;
template<typename T>
struct type_identity
{
using type = T;
};
template<typename T>
using type_identity_t = type_identity<T>::type;
}
#endif // !defined(BAD_APPLE_OS_TYPE_TRAITS_INCLUDED)

View File

@ -4,6 +4,7 @@
#if !defined(BAD_APPLE_OS_VECTOR_INCLUDED)
#define BAD_APPLE_OS_VECTOR_INCLUDED
#include <algorithm>
#include <cstddef>
#include <new>
#include <stdexcept>
@ -11,13 +12,13 @@
namespace std
{
template<typename T> // TODO: allocator
template<typename T, typename TAlloc = void> // TODO: allocator
class vector
{
public:
using value_type = T;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using size_type = size_t;
using difference_type = ptrdiff_t;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
@ -210,7 +211,7 @@ public:
constexpr void push_back(value_type&& value)
{
reserve(size() + 1);
::new (&_elements[size()]) T(std::move(value));
::new (&_elements[size()]) T(move(value));
++_size;
}
@ -223,7 +224,7 @@ public:
constexpr reference emplace_back(TArgs&&... args)
{
reserve(size() + 1);
::new (&_elements[size()]) T(std::forward<TArgs>(args)...);
::new (&_elements[size()]) T(forward<TArgs>(args)...);
++_size;
}
@ -274,6 +275,27 @@ public:
}
_size = newSize;
}
constexpr iterator erase(const_iterator first, const_iterator last)
{
// the spec wants the parameters to be const iterators...
iterator realFirst = begin() + (first - begin());
iterator realLast = begin() + (last - begin());
const size_t newSize = size() - (last - first);
for (auto it = realLast; it != end(); ++it)
{
*realFirst = move(*it);
++realFirst;
}
resize(newSize);
return realFirst;
}
constexpr iterator erase(const_iterator pos)
{
return erase(pos, pos + 1);
}
private:
void updateCapacity(size_type newCapacity)
{
@ -281,6 +303,10 @@ private:
return;
}
T* newElements = static_cast<T*>(malloc(newCapacity * sizeof(T)));
if (newElements == nullptr)
{
__ba_throw bad_alloc();
}
for (size_type idx = 0; idx < size(); ++idx)
{
::new (&newElements[idx]) T(move(_elements[idx]));
@ -291,6 +317,16 @@ private:
_capacity = newCapacity;
}
};
template<typename T, typename TAlloc, typename Pred>
constexpr vector<T, TAlloc>::size_type erase_if(vector<T, TAlloc>& vec, Pred pred)
{
auto it = remove_if(vec.begin(), vec.end(), pred);
auto removed = vec.end() - it;
vec.erase(it, vec.end());
return removed;
}
}
#endif // !defined(BAD_APPLE_OS_VECTOR_INCLUDED)

View File

@ -1,8 +1,24 @@
#!/bin/bash
QEMU_ARGS=()
WAIT=true
while [ ! -z "$1" ] ; do
case "$1" in
"--detach")
WAIT=false
;;
*)
QEMU_ARGS+=("$1")
;;
esac
shift
done
qemu-system-x86_64 \
--bios /usr/share/edk2/x64/OVMF.fd \
-vga virtio \
-serial stdio \
-drive if=none,id=stick,format=raw,file=staging/x86_64_iso/fat.img \
-device nec-usb-xhci,id=xhci \
-device usb-storage,bus=xhci.0,drive=stick "$@"
-device usb-storage,bus=xhci.0,drive=stick "${QEMU_ARGS[@]}" &
if ${WAIT} ; then
wait
fi

View File

@ -42,10 +42,12 @@ any_target_sources = Split('''
src/app/main.cpp
src/drivers/pci.cpp
src/drivers/usb.cpp
src/libs/psf.cpp
src/os/draw.cpp
src/os/memory.cpp
src/os/panic.cpp
src/os/tty.cpp
src/os/resources/lat9-08.psf.s

View File

@ -0,0 +1,17 @@
#pragma once
#if !defined(BAD_APPLE_OS_DRIVERS_USB_HPP_INCLUDED)
#define BAD_APPLE_OS_DRIVERS_USB_HPP_INCLUDED
namespace baos::pci
{
struct Header;
}
namespace baos::usb
{
[[nodiscard]] bool initController(const pci::Header& pciHeader) noexcept;
}
#endif // !defined(BAD_APPLE_OS_DRIVERS_USB_HPP_INCLUDED)

View File

@ -0,0 +1,72 @@
#pragma once
#if !defined(BAD_APPLE_OS_OS_MEMORY_HPP_INCLUDED)
#define BAD_APPLE_OS_OS_MEMORY_HPP_INCLUDED
#include <bit>
#include <cstdint>
#include <span>
extern "C" int gKernelStart;
extern "C" int gKernelEnd;
namespace baos
{
struct PageTableEntry
{
bool present : 1;
bool writable : 1;
bool user : 1;
bool writeThrough : 1;
bool cacheDisabled : 1;
bool accessed : 1;
bool dirty : 1;
bool pageSize : 1;
bool global : 1;
std::uint8_t avl : 3;
std::uint64_t address : 40;
std::uint16_t avl2 : 11;
bool executeDisable : 1;
};
enum class MemoryType
{
USABLE,
UNUSABLE,
MMIO,
RESERVED
};
struct MemoryRange
{
std::uint64_t pageBase;
std::uint64_t numPages;
MemoryType type = MemoryType::USABLE;
MemoryRange& operator=(const MemoryRange&) noexcept = default;
bool operator<(const MemoryRange& other) const noexcept
{
return pageBase < other.pageBase;
}
};
void setupPaging(std::span<const MemoryRange> memoryRanges) noexcept;
[[nodiscard]] const char* memoryTypeName(MemoryType type) noexcept;
[[nodiscard]] void* allocatePages(unsigned numConsecutive) noexcept;
[[nodiscard]] inline void* allocatePage() noexcept { return allocatePages(1); }
void setupIdentityPaging(std::uint64_t page) noexcept;
void setupIdentityPaging2M(std::uint64_t page) noexcept;
void setupIdentityPaging(std::uint64_t firstPage, std::uint64_t lastPage) noexcept;
inline void identityMapRegion(void* start, std::size_t bytes) noexcept
{
std::uint64_t firstPage = std::bit_cast<std::uint64_t>(start) / 4096;
std::uint64_t lastPage = std::bit_cast<std::uint64_t>(static_cast<std::uint8_t*>(start) + bytes) / 4096 + 1;
setupIdentityPaging(firstPage, lastPage);
}
}
#endif // !defined(BAD_APPLE_OS_OS_MEMORY_HPP_INCLUDED)

View File

@ -1,8 +1,10 @@
#include <bit>
#include <cstdio>
#include "drivers/pci.hpp"
#include "drivers/ps2.hpp"
#include "os/memory.hpp"
namespace
{
@ -49,6 +51,61 @@ void cmdShowKeys() noexcept
}
}
}
void cmdDumpPageTable() noexcept
{
std::uint64_t cr3 = 0;
__asm__ __volatile__(
"mov %%cr3, %0"
: "=a"(cr3)
:
);
std::uint64_t pml4Addr = cr3 & ~0xFFF;
std::printf("pml4 address: 0x%lX\n", pml4Addr);
baos::PageTableEntry* pml4 = std::bit_cast<baos::PageTableEntry*>(pml4Addr);
auto printPDE = [](const baos::PageTableEntry& pde)
{
std::printf("%s%s%s%s%s%s%s%s%s, address=%lX\n",
pde.present ? " P" : "",
pde.writable ? " W" : "",
pde.user ? " U" : "",
pde.writeThrough ? " WT" : "",
pde.cacheDisabled ? " CD" : "",
pde.accessed ? " A" : "",
pde.dirty ? " D" : "",
pde.pageSize ? " PS" : "",
pde.executeDisable ? " XD" : "",
pde.address * 4096);
};
for (unsigned pml4e = 0; pml4e < 512; ++pml4e)
{
if (!pml4[pml4e].present) {
continue;
}
std::printf("%d]", pml4e);
printPDE(pml4[pml4e]);
baos::PageTableEntry* pdp = std::bit_cast<baos::PageTableEntry*>(pml4[pml4e].address * 4096);
for (unsigned pdpe = 0; pdpe < 512; ++pdpe)
{
if (!pdp[pdpe].present) {
continue;
}
std::printf("%d.%d]", pml4e, pdpe);
printPDE(pdp[pdpe]);
baos::PageTableEntry* pd = std::bit_cast<baos::PageTableEntry*>(pdp[pdpe].address * 4096);
for (unsigned pde = 0; pde < 512; ++pde)
{
if (!pd[pde].present) {
continue;
}
std::printf("%d.%d.%d]", pml4e, pdpe, pde);
printPDE(pd[pde]);
}
}
}
}
}
extern "C" void main()
@ -72,6 +129,11 @@ extern "C" void main()
cmdShowKeys();
continue;
}
else if (cmd == "dump-pages")
{
cmdDumpPageTable();
continue;
}
std::printf("Unknown command: %s.\n", cmd.c_str());
}
}

View File

@ -7,7 +7,7 @@
namespace
{
inline const size_t INIT_MALLOC_SPACE_ELEMENTS = 1024 * 1024;
inline const size_t INIT_MALLOC_SPACE_BYTES = INIT_MALLOC_SPACE_ELEMENTS * sizeof(max_align_t);
inline const size_t INIT_MALLOC_SPACE_BYTES = INIT_MALLOC_SPACE_ELEMENTS * alignof(max_align_t);
max_align_t gInitMallocSpace[INIT_MALLOC_SPACE_ELEMENTS];
@ -20,8 +20,8 @@ struct AllocInfo
{
size_t elements;
};
static_assert(sizeof(MallocBlock) <= sizeof(max_align_t));
static_assert(sizeof(AllocInfo) <= sizeof(max_align_t));
static_assert(sizeof(MallocBlock) <= alignof(max_align_t));
static_assert(sizeof(AllocInfo) <= alignof(max_align_t));
MallocBlock* gNextBlock = []()
{

View File

@ -0,0 +1,272 @@
#include "drivers/usb.hpp"
#include <algorithm>
#include <array>
#include <bit>
#include <cassert>
#include <cstdio>
#include "drivers/pci.hpp"
namespace baos::usb
{
namespace
{
inline constexpr std::uint8_t USB_PROGIF_UHCI_CONTROLLER = 0x0;
inline constexpr std::uint8_t USB_PROGIF_OHCI_CONTROLLER = 0x10;
inline constexpr std::uint8_t USB_PROGIF_EHCI_CONTROLLER = 0x20;
inline constexpr std::uint8_t USB_PROGIF_XHCI_CONTROLLER = 0x30;
#define BAOS_MEMORY_REGISTER_RO(offset, type, name) \
[[nodiscard]] const Register<type> name() const noexcept { return Register(*reinterpret_cast<type*>(base + offset)); }
#define BAOS_MEMORY_REGISTER_RW(offset, type, name) \
[[nodiscard]] Register<type> name() const noexcept { return Register(*reinterpret_cast<type*>(base + offset)); }
#define BAOS_MEMORY_REGISTER_RO_PARAM(offset, type, name, paramType, paramName) \
[[nodiscard]] const Register<type> name(paramType paramName) const noexcept { return Register(*reinterpret_cast<type*>(base + offset)); }
#define BAOS_MEMORY_REGISTER_RW_PARAM(offset, type, name, paramType, paramName) \
[[nodiscard]] Register<type> name(paramType paramName) const noexcept { return Register(*reinterpret_cast<type*>(base + offset)); }
struct XHCIHCSParams1
{
std::uint8_t maxSlots;
std::uint16_t maxInterrupts : 11;
std::uint8_t reserved : 5;
std::uint8_t maxPorts;
} __attribute__((packed));
static_assert(sizeof(XHCIHCSParams1) == 4);
#define BAOS_MEMORY_BARRIER() __asm__ __volatile__ ("" : : : "memory")
#define BAOS_STORE_FENCE() __asm__ __volatile__ ("sfence" : : : "memory")
#define BAOS_LOAD_FENCE() __asm__ __volatile__ ("lfence" : : : "memory")
#define BAOS_MEMORY_FENCE() __asm__ __volatile__ ("mfence" : : : "memory")
template<typename T>
class Register
{
private:
T& mMemory;
public:
explicit Register(T& memory) noexcept : mMemory(memory) {}
Register& operator=(const T& value) noexcept
{
set(value);
return *this;
}
operator T() const noexcept { return get(); }
void set(const T& value) noexcept
{
BAOS_STORE_FENCE();
mMemory = value;
}
[[nodiscard]] T get() const noexcept
{
BAOS_MEMORY_BARRIER();
T value = mMemory;
BAOS_LOAD_FENCE();
return value;
}
};
struct XHCICapabilityRegisters
{
std::uint64_t base;
BAOS_MEMORY_REGISTER_RO(0x00, std::uint8_t, caplength)
BAOS_MEMORY_REGISTER_RO(0x02, std::uint16_t, ifaceVersion)
BAOS_MEMORY_REGISTER_RO(0x04, XHCIHCSParams1, hcsParams1)
BAOS_MEMORY_REGISTER_RO(0x08, std::uint32_t, hcsParams2)
BAOS_MEMORY_REGISTER_RO(0x0C, std::uint32_t, hcsParams3)
BAOS_MEMORY_REGISTER_RO(0x10, std::uint32_t, hccParams1)
BAOS_MEMORY_REGISTER_RO(0x14, std::uint32_t, dbOff)
BAOS_MEMORY_REGISTER_RO(0x18, std::uint32_t, rtsOff)
BAOS_MEMORY_REGISTER_RO(0x1C, std::uint32_t, hccParams2)
BAOS_MEMORY_REGISTER_RO(0x20, std::uint32_t, vtiosOff)
};
struct XHCIUSBCommand
{
/* 0 */ bool runStop : 1;
/* 1 */ bool hostControllerReset : 1;
/* 2 */ bool interrupterEnable : 1;
/* 3 */ bool hostSystemErrorEnable : 1;
/* 4 */ std::uint8_t reserved0 : 3;
/* 7 */ bool lightHostControllerReset : 1;
/* 8 */ bool controllerSaveState : 1;
/* 9 */ bool controllerRestoreState : 1;
/* 10 */ bool enableWrapEvent : 1;
/* 11 */ bool enableU3MFINDEXStop : 1;
/* 12 */ std::uint8_t reserved1 : 1;
/* 13 */ bool cemEnable : 1;
/* 14 */ bool extendedTBCEnable : 1;
/* 15 */ bool extendedTBCTRBStatusEnable : 1;
/* 16 */ bool vtioEnable : 1;
/* 17 */ std::uint16_t reserved2 : 15;
};
static_assert(sizeof(XHCIUSBCommand) == 4);
struct XHCIUSBStatus
{
/* 0 */ bool hcHalted : 1;
/* 1 */ std::uint8_t reserved0 : 1;
/* 2 */ bool hostSystemError : 1;
/* 3 */ bool eventInterrupt : 1;
/* 4 */ bool portChangeDetect : 1;
/* 5 */ std::uint8_t reserved1 : 3;
/* 8 */ const bool saveStateStatus : 1;
/* 9 */ const bool restoreStateStatus : 1;
/* 10 */ bool saveRestoreError : 1;
/* 11 */ const bool controllerNotReady : 1;
/* 12 */ const bool hostControllerError : 1;
/* 13 */ std::uint32_t reserved2 : 19;
};
static_assert(sizeof(XHCIUSBStatus) == 4);
struct XHCIConfig
{
std::uint8_t maxDeviceSlotsEnabled : 7;
bool u3EntryEnable : 1;
bool configurationInformationEnable : 1;
std::uint32_t reserved : 22;
};
static_assert(sizeof(XHCIConfig) == 4);
struct XHCIOperationalRegisters
{
std::uint64_t base;
BAOS_MEMORY_REGISTER_RW(0x00, XHCIUSBCommand, usbCmd)
BAOS_MEMORY_REGISTER_RW(0x04, XHCIUSBStatus, usbStatus)
BAOS_MEMORY_REGISTER_RO(0x08, std::uint32_t, pageSize)
BAOS_MEMORY_REGISTER_RW(0x14, std::uint32_t, dnCtrl)
BAOS_MEMORY_REGISTER_RW(0x18, std::uint64_t, crcr)
BAOS_MEMORY_REGISTER_RW(0x30, std::uint64_t, dcbaap)
BAOS_MEMORY_REGISTER_RW(0x38, XHCIConfig, config)
BAOS_MEMORY_REGISTER_RW_PARAM(0x400 + 0x10 * (port-1), std::uint32_t, portSC, std::uint32_t, port)
BAOS_MEMORY_REGISTER_RW_PARAM(0x404 + 0x10 * (port-1), std::uint32_t, portPMSC, std::uint32_t, port)
BAOS_MEMORY_REGISTER_RO_PARAM(0x408 + 0x10 * (port-1), std::uint32_t, portLI, std::uint32_t, port)
BAOS_MEMORY_REGISTER_RW_PARAM(0x40C + 0x10 * (port-1), std::uint32_t, portHLPMC, std::uint32_t, port)
};
struct XHCIHostControllerRuntimeRegisters
{
std::uint64_t base;
BAOS_MEMORY_REGISTER_RO(0x00, std::uint32_t, mfIndex)
BAOS_MEMORY_REGISTER_RW_PARAM(0x20 + (32 * interrupter), std::uint32_t, iman, std::uint32_t, interrupter)
BAOS_MEMORY_REGISTER_RW_PARAM(0x24 + (32 * interrupter), std::uint32_t, imod, std::uint32_t, interrupter)
BAOS_MEMORY_REGISTER_RW_PARAM(0x28 + (32 * interrupter), std::uint32_t, erstsz, std::uint32_t, interrupter)
BAOS_MEMORY_REGISTER_RW_PARAM(0x30 + (32 * interrupter), std::uint64_t, erstba, std::uint32_t, interrupter)
BAOS_MEMORY_REGISTER_RW_PARAM(0x38 + (32 * interrupter), std::uint64_t, erdp, std::uint32_t, interrupter)
};
struct XHCIHostController
{
XHCICapabilityRegisters capabilityRegs = {};
XHCIOperationalRegisters operationalRegs = {};
XHCIHostControllerRuntimeRegisters controllerRuntimeRegs = {};
explicit XHCIHostController(std::uint64_t base) noexcept : capabilityRegs(base)
{
operationalRegs.base = capabilityRegs.base + capabilityRegs.caplength();
controllerRuntimeRegs.base = capabilityRegs.base + capabilityRegs.rtsOff();
}
XHCIHostController(const XHCIHostController&) noexcept = default;
XHCIHostController& operator=(const XHCIHostController&) noexcept = default;
};
bool initUHCIController(const pci::Header& pciHeader) noexcept
{
(void) pciHeader;
// TODO: not implemented yet
return false;
}
bool initOHCIController(const pci::Header& pciHeader) noexcept
{
(void) pciHeader;
// TODO: not implemented yet
return false;
}
bool initEHCIController(const pci::Header& pciHeader) noexcept
{
(void) pciHeader;
// TODO: not implemented yet
return false;
}
std::array<void*, 32> gDeviceContextBasePointers alignas(64);
bool initXHCIController(const pci::Header& pciHeader) noexcept
{
return false;
pci::GeneralDeviceHeader gdHeader = {};
if (!pci::getGeneralDeviceHeader(pciHeader, gdHeader)) {
return false;
}
const std::uint64_t registerMemory = static_cast<std::uint64_t>(gdHeader.bar1) << 32 | gdHeader.bar0;
std::printf("XHCI register memory: 0x%lX\n", registerMemory);
XHCIHostController controller(registerMemory);
// see chapter 4.2 (Host Controller Initialization) of the XHCI spec
// https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
// 1. wait until the controller is ready
while (controller.operationalRegs.usbStatus().get().controllerNotReady);
// 2. set maximum enabled slots
const XHCIHCSParams1 hcsParams1 = controller.capabilityRegs.hcsParams1();
XHCIConfig config = controller.operationalRegs.config();
config.maxDeviceSlotsEnabled = std::min(hcsParams1.maxSlots, static_cast<std::uint8_t>(gDeviceContextBasePointers.size() - 1));
controller.operationalRegs.config() = config;
// 3. setup the device context base address pointer
const std::uint64_t pointer = std::bit_cast<std::uint64_t>(gDeviceContextBasePointers.data());
assert((pointer & 0b11111) == 0);
controller.operationalRegs.dcbaap() = pointer;
XHCIUSBCommand cmd = controller.operationalRegs.usbCmd();
cmd.runStop = true;
controller.operationalRegs.usbCmd() = cmd;
cmd = controller.operationalRegs.usbCmd();
while (true)
{
const XHCIUSBStatus status = controller.operationalRegs.usbStatus();
if (!status.hcHalted) {
break;
}
}
std::printf("MaxSlots: %d, MaxInterrupts: %d, MaxPorts: %d\n", hcsParams1.maxSlots, hcsParams1.maxInterrupts, hcsParams1.maxPorts);
//const XHCIOperationalRegisters operationalRegisters{registerMemory + capabilityRegisters.caplength()};
// TODO: not implemented yet
return false;
}
}
bool initController(const pci::Header& pciHeader) noexcept
{
switch (pciHeader.progIf)
{
case USB_PROGIF_UHCI_CONTROLLER:
return initUHCIController(pciHeader);
case USB_PROGIF_OHCI_CONTROLLER:
return initOHCIController(pciHeader);
case USB_PROGIF_EHCI_CONTROLLER:
return initEHCIController(pciHeader);
case USB_PROGIF_XHCI_CONTROLLER:
return initXHCIController(pciHeader);
default:
return false; // what is this?
}
}
}

View File

@ -3,6 +3,7 @@
#include <cstring>
#include "libs/psf.hpp"
#include "os/memory.hpp"
namespace draw
{

View File

@ -31,6 +31,15 @@ void iprintf(const char* format, ...) noexcept
PrintFHelper<InterruptPrinter>().vprintf(format, parameters);
va_end(parameters);
}
__attribute__((no_caller_saved_registers))
void splitPageToIndices(std::uint64_t page, std::uint16_t& outPML4Entry, std::uint16_t& outPDPEntry, std::uint16_t& outPDEntry, std::uint16_t& outPTEntry) noexcept
{
outPML4Entry = (page >> 27);
outPDPEntry = (page >> 18) & 0x1FF;
outPDEntry = (page >> 9) & 0x1FF;
outPTEntry = page & 0x1FF;
}
}
extern "C" [[noreturn]] void __halt();
@ -110,6 +119,37 @@ void isrGeneralProtectionFault(InterruptFrame* interruptFrame, interrupt_error_c
__attribute__((interrupt))
void isrPageFault(InterruptFrame* interruptFrame, interrupt_error_code_t errorCode) noexcept
{
static constexpr std::uint64_t PRESENT_BIT = (1 << 0);
static constexpr std::uint64_t WRITE_BIT = (1 << 1);
static constexpr std::uint64_t USER_BIT = (1 << 2);
static constexpr std::uint64_t RESERVED_WRITE_BIT = (1 << 3);
static constexpr std::uint64_t INSTRUCTION_FETCH_BIT = (1 << 4);
static constexpr std::uint64_t PROTECTION_KEY_BIT = (1 << 5);
static constexpr std::uint64_t SHADOW_STACK_BIT = (1 << 6);
static constexpr std::uint64_t SGX_BIT = (1 << 7);
std::uint64_t cr2 = 0;
__asm__ __volatile__(
"mov %%cr2, %0"
: "=a"(cr2)
:
);
iprintf("address: 0x%lX\n", cr2);
std::uint16_t pml4Index = 0;
std::uint16_t pdpIndex = 0;
std::uint16_t pdIndex = 0;
std::uint16_t ptIndex = 0;
splitPageToIndices(cr2 >> 12, pml4Index, pdpIndex, pdIndex, ptIndex);
iprintf("page: %d.%d.%d.%d\n", pml4Index, pdpIndex, pdIndex, ptIndex);
iprintf("present: %s\n", (errorCode & PRESENT_BIT) ? "yes" : "no");
iprintf("access: %s\n", (errorCode & WRITE_BIT) ? "write" : "read");
iprintf("mode: %s\n", (errorCode & USER_BIT) ? "user" : "supervisor");
iprintf("reserved write: %s\n", (errorCode & RESERVED_WRITE_BIT) ? "yes" : "no");
iprintf("instruction fetch: %s\n", (errorCode & INSTRUCTION_FETCH_BIT) ? "yes" : "no");
iprintf("protection key: %s\n", (errorCode & PROTECTION_KEY_BIT) ? "yes" : "no");
iprintf("shadow stack: %s\n", (errorCode & SHADOW_STACK_BIT) ? "yes" : "no");
iprintf("software guard extensions: %s\n", (errorCode & SGX_BIT) ? "yes" : "no");
handleException("PageFault", interruptFrame);
}

View File

@ -0,0 +1,326 @@
#include "os/memory.hpp"
#include <array>
#include <bit>
#include <cstdio>
#include <memory>
#include <new>
namespace baos
{
namespace
{
using PageTable = std::array<PageTableEntry, 512>;
constinit PageTable gPageMapLevel4 alignas(4096);
struct MemoryRangeAllocationInfo
{
std::array<std::uint8_t, 4086> usedPages;
std::uint16_t numFreePages = 0;
MemoryRangeAllocationInfo* next = nullptr;
};
static_assert(sizeof(MemoryRangeAllocationInfo) == 4096);
inline constexpr unsigned MAX_USABLE_RANGES = 32;
std::array<MemoryRange, MAX_USABLE_RANGES> gUsableMemoryRanges;
std::array<MemoryRangeAllocationInfo, MAX_USABLE_RANGES> gRangeAllocationInfo;
std::uint8_t gNumUsableRanges = 0;
// initial 2MB page for setting up the page table
// std::array<std::uint8_t, 2ul << 20> gInitPage alignas(2ul << 20);
std::span<std::uint8_t> gPageTableSpace;
std::span<std::uint8_t> gNextPageTableSpace;
void splitPageToIndices(std::uint64_t page, std::uint16_t& outPML4Entry, std::uint16_t& outPDPEntry, std::uint16_t& outPDEntry, std::uint16_t& outPTEntry) noexcept
{
outPML4Entry = (page >> 27);
outPDPEntry = (page >> 18) & 0x1FF;
outPDEntry = (page >> 9) & 0x1FF;
outPTEntry = page & 0x1FF;
}
PageTable& allocatePageTable() noexcept
{
PageTable* pageTable = std::bit_cast<PageTable*>(&*gPageTableSpace.begin());
if (!pageTable)
{
int i = 5;
}
::new(pageTable) PageTable;
gPageTableSpace = {gPageTableSpace.begin() + sizeof(PageTable), gPageTableSpace.end()};
return *pageTable;
}
PageTableEntry& getOrCreatePageTableEntry(PageTable& pageTable, std::uint16_t index)
{
PageTableEntry& entry = pageTable[index];
if (!entry.present)
{
PageTable& childTable = allocatePageTable();
entry.address = std::bit_cast<std::uint64_t>(&childTable) >> 12;
entry.writable = true;
entry.present = true;
}
return entry;
}
PageTableEntry& getOrCreatePage(std::uint64_t page, bool bigPage = false)
{
std::uint16_t pml4Index = 0;
std::uint16_t pdpIndex = 0;
std::uint16_t pdIndex = 0;
std::uint16_t ptIndex = 0;
splitPageToIndices(page, pml4Index, pdpIndex, pdIndex, ptIndex);
PageTableEntry& pml4Entry = getOrCreatePageTableEntry(gPageMapLevel4, pml4Index);
PageTable& pdp = *std::bit_cast<PageTable*>(pml4Entry.address << 12);
PageTableEntry& pdpEntry = getOrCreatePageTableEntry(pdp, pdpIndex);
PageTable& pd = *std::bit_cast<PageTable*>(pdpEntry.address << 12);
PageTableEntry& pdEntry = getOrCreatePageTableEntry(pd, pdIndex);
if (bigPage)
{
pdEntry.pageSize = true;
return pdEntry;
}
PageTable& pt = *std::bit_cast<PageTable*>(pdEntry.address << 12);
return getOrCreatePageTableEntry(pt, ptIndex);
}
void addUsableRange(const MemoryRange& range) noexcept
{
if (gNumUsableRanges >= MAX_USABLE_RANGES) {
return;
}
gUsableMemoryRanges[gNumUsableRanges] = range;
gRangeAllocationInfo[gNumUsableRanges].numFreePages = range.numPages;
++gNumUsableRanges;
}
std::uint64_t findFreePages(unsigned numConsecutive) noexcept
{
if (numConsecutive == 0 || numConsecutive > 4086) {
return 0;
}
if (numConsecutive != 1) {
return 0; // TODO!!!
}
for (std::uint8_t rangeIdx = 0; rangeIdx < gNumUsableRanges; ++rangeIdx)
{
std::uint64_t page = gUsableMemoryRanges[rangeIdx].pageBase;
for (MemoryRangeAllocationInfo* allocInfo = &gRangeAllocationInfo[rangeIdx]; allocInfo != nullptr; page += allocInfo->usedPages.size(), allocInfo = allocInfo->next)
{
if (allocInfo->numFreePages < numConsecutive) {
continue;
}
for (unsigned pagesIdx = 0; pagesIdx < allocInfo->usedPages.size(); ++pagesIdx)
{
if (allocInfo->usedPages[pagesIdx] != 0xFF)
{
for (unsigned bit = 0; bit < 8; ++bit)
{
if ((allocInfo->usedPages[pagesIdx] & (1 << bit)) == 0)
{
allocInfo->usedPages[pagesIdx] |= (1 << bit);
return page + (8 * pagesIdx) + bit;
}
}
}
}
}
}
return 0;
}
PageTable& setupPageTableEntry(PageTableEntry& entry, std::uint64_t page) noexcept
{
entry.address = page;
entry.present = true;
entry.writable = true;
return *(::new(std::bit_cast<void*>(entry.address << 12)) PageTable);
}
void cmdDumpPageTable() noexcept
{
std::uint64_t pml4Addr = std::bit_cast<std::uint64_t>(&gPageMapLevel4);
std::printf("pml4 address: 0x%lX\n", pml4Addr);
baos::PageTableEntry* pml4 = std::bit_cast<baos::PageTableEntry*>(pml4Addr);
auto printPDE = [](const baos::PageTableEntry& pde)
{
std::printf("%s%s%s%s%s%s%s%s%s, address=%lX\n",
pde.present ? " P" : "",
pde.writable ? " W" : "",
pde.user ? " U" : "",
pde.writeThrough ? " WT" : "",
pde.cacheDisabled ? " CD" : "",
pde.accessed ? " A" : "",
pde.dirty ? " D" : "",
pde.pageSize ? " PS" : "",
pde.executeDisable ? " XD" : "",
pde.address * 4096);
};
for (unsigned pml4e = 0; pml4e < 512; ++pml4e)
{
if (!pml4[pml4e].present) {
continue;
}
std::printf("%d]", pml4e);
printPDE(pml4[pml4e]);
baos::PageTableEntry* pdp = std::bit_cast<baos::PageTableEntry*>(pml4[pml4e].address * 4096);
for (unsigned pdpe = 0; pdpe < 512; ++pdpe)
{
if (!pdp[pdpe].present) {
continue;
}
std::printf("%d.%d]", pml4e, pdpe);
printPDE(pdp[pdpe]);
baos::PageTableEntry* pd = std::bit_cast<baos::PageTableEntry*>(pdp[pdpe].address * 4096);
for (unsigned pde = 0; pde < 512; ++pde)
{
if (!pd[pde].present) {
continue;
}
std::printf("%d.%d.%d]", pml4e, pdpe, pde);
printPDE(pd[pde]);
}
}
}
}
bool canFitPageTableSpace(MemoryRange range, std::uint64_t& outBase) noexcept
{
if (range.type != MemoryType::USABLE) {
return false;
}
const std::uint64_t possibleBase = std::alignUp(range.pageBase, 512ul); // needs to be 2MB aligned
if (range.numPages - (possibleBase - range.pageBase) >= 512)
{
outBase = possibleBase;
return true;
}
return false;
}
}
void setupPaging(std::span<const MemoryRange> memoryRanges) noexcept
{
// addUsableRange({
// .pageBase = std::bit_cast<std::uint64_t>(gInitPages.data()) >> 12,
// .numPages = gInitPages.size() / 4096,
// .type = MemoryType::USABLE
// });
std::uint64_t firstKernelPage = std::bit_cast<std::uint64_t>(&gKernelStart) / 4096;
std::uint64_t lastKernelPage = std::bit_cast<std::uint64_t>(&gKernelEnd) / 4096 + 1;
for (MemoryRange range : memoryRanges)
{
if (range.type == MemoryType::USABLE) // ignore anything before the kernel
{
if (range.pageBase < lastKernelPage)
{
if (range.numPages < (lastKernelPage - range.pageBase))
{
continue;
}
range.numPages -= (lastKernelPage - range.pageBase);
range.pageBase = lastKernelPage;
}
addUsableRange(range);
std::uint64_t tableSpaceBase = 0;
if (gPageTableSpace.empty() && canFitPageTableSpace(range, tableSpaceBase))
{
std::uint8_t* tableSpacePtr = std::bit_cast<std::uint8_t*>(tableSpaceBase * 4096);
gPageTableSpace = {tableSpacePtr, 2ul << 30};
setupIdentityPaging2M(tableSpaceBase);
}
}
}
// start by setting up identity paging for the kernel
// __get_cpuid()
setupIdentityPaging(firstKernelPage, lastKernelPage);
// std::printf("Kernel pages: %ld-%ld\n", firstKernelPage, lastKernelPage);
// setup identity paging for all reserved ranges so we can continue using them
// for (const MemoryRange& range : memoryRanges)
// {
// if (range.type == MemoryType::RESERVED || range.type == MemoryType::MMIO)
// {
// setupIdentityPaging(range.pageBase, range.pageBase + range.numPages);
// }
// }
// cmdDumpPageTable();
std::uint64_t cr3 = std::bit_cast<std::uint64_t>(gPageMapLevel4.data());
__asm__ __volatile__ (
"mov %0, %%cr3"
:
: "a"(cr3)
);
}
const char* memoryTypeName(MemoryType type) noexcept
{
switch (type)
{
case MemoryType::USABLE:
return "USABLE";
case MemoryType::UNUSABLE:
return "UNUSABLE";
case MemoryType::MMIO:
return "MMIO";
case MemoryType::RESERVED:
return "RESERVED";
}
return "<INVALID>";
}
void* allocatePages(unsigned numConsecutive) noexcept
{
const std::uint64_t firstPage = findFreePages(numConsecutive);
if (firstPage == 0)
{
return nullptr;
}
setupIdentityPaging(firstPage, firstPage + numConsecutive);
return std::bit_cast<void*>(firstPage << 12);
}
void setupIdentityPaging(std::uint64_t page) noexcept
{
PageTableEntry& pageTableEntry = getOrCreatePage(page);
pageTableEntry.address = page;
}
void setupIdentityPaging2M(std::uint64_t page) noexcept
{
PageTableEntry& pageTableEntry = getOrCreatePage(page, true);
pageTableEntry.address = page;
}
void setupIdentityPaging(std::uint64_t firstPage, std::uint64_t lastPage) noexcept
{
for (std::uint64_t page = firstPage; page != lastPage; ++page)
{
if (page % 512 == 0 && (lastPage - page) >= 512)
{
setupIdentityPaging2M(page);
page += 511; // loop will add the last 1
}
else
{
setupIdentityPaging(page);
}
}
}
}

View File

@ -18,6 +18,7 @@ SECTIONS
work around this issue. This does not use that feature, so 2M was
chosen as a safer option than the traditional 1M. */
. = 2M;
gKernelStart = .;
/* First put the multiboot header, as it is required to be put very early
in the image or the bootloader won't recognize the file format.

View File

@ -1,19 +1,22 @@
#include "boot.hpp"
#include <algorithm>
#include <bit>
#include <cassert>
#include <cstdio>
#include <memory>
#include "os/draw.hpp"
#include "os/memory.hpp"
#include "os/serial.hpp"
#include "os/tty.hpp"
#include "drivers/pci.hpp"
#include "drivers/pic.hpp"
#include "drivers/ps2.hpp"
#include "drivers/usb.hpp"
#include "./x86_64.hpp"
extern "C" int gKernelEnd;
namespace
{
inline constexpr std::uint8_t MASTER_PIC_OFFSET = 0x20;
@ -67,61 +70,67 @@ inline constexpr std::uint16_t SEGIDX_TSS = 5 << 3;
constinit std::array<InterruptDescriptor, 256> IDT alignas(16);
void initHeapFromEfiMemoryMap(const EfiMemoryMap& memoryMap) noexcept
inline baos::MemoryType mapEfiMemoryType(UINT32 type) noexcept
{
const uint64_t minAddr = reinterpret_cast<uint64_t>(&gKernelEnd);
switch (type)
{
case EfiLoaderCode:
case EfiLoaderData:
case EfiBootServicesCode:
case EfiBootServicesData:
case EfiConventionalMemory:
return baos::MemoryType::USABLE;
case EfiRuntimeServicesCode:
case EfiRuntimeServicesData:
case EfiUnusableMemory:
case EfiACPIReclaimMemory:
case EfiMaxMemoryType:
default:
return baos::MemoryType::UNUSABLE;
case EfiMemoryMappedIO:
case EfiMemoryMappedIOPortSpace:
return baos::MemoryType::MMIO;
case EfiACPIMemoryNVS:
case EfiPalCode:
case EfiReservedMemoryType:
return baos::MemoryType::RESERVED;
}
}
std::vector<baos::MemoryRange> detectMemoryRangesFromEfi(const EfiMemoryMap& memoryMap) noexcept
{
std::vector<baos::MemoryRange> ranges;
ranges.reserve(memoryMap.mapSize / memoryMap.descriptorSize);
for (const EFI_MEMORY_DESCRIPTOR& descriptor : memoryMap)
{
if (!isEfiMemoryTypeUsable(descriptor.Type))
{
continue;
}
const baos::MemoryType type = mapEfiMemoryType(descriptor.Type);
uint64_t addr = descriptor.PhysicalStart;
uint64_t len = descriptor.NumberOfPages * 4096; // TODO: is this the correct page size?
// anything before the kernel we ignore
if (addr < minAddr)
{
// if the entire entry is before the kernel, continue
if (addr + len <= minAddr)
{
continue;
assert(descriptor.PhysicalStart % 4096 == 0);
uint64_t pageBase = descriptor.PhysicalStart / 4096;
uint64_t numPages = descriptor.NumberOfPages;
ranges.push_back({.pageBase = pageBase, .numPages = numPages, .type = type});
}
// otherwise shrink it and use the rest
len -= (minAddr - addr);
addr = minAddr;
}
__ba_registerAllocatableMemory(reinterpret_cast<void*>(addr), len);
}
#if 0
const uint64_t minAddr = reinterpret_cast<uint64_t>(&gKernelEnd);
for (uint32_t addr = firstEntryAddr; addr < firstEntryAddr + bufferLength;)
{
multiboot_memory_map_t entry = *reinterpret_cast<multiboot_memory_map_t*>(addr);
std::sort(ranges.begin(), ranges.end());
if(entry.type == MULTIBOOT_MEMORY_AVAILABLE)
// merge adjacent ranges
for (std::size_t idx = ranges.size() - 1; idx > 0; --idx)
{
std::printf("Start Addr: %X | Length: %b\n",
static_cast<unsigned>(entry.addr), static_cast<size_t>(entry.len));
baos::MemoryRange& left = ranges[idx-1];
baos::MemoryRange& right = ranges[idx];
// anything before the kernel we ignore
if (entry.addr < minAddr)
if (left.type == right.type && left.pageBase + left.numPages == right.pageBase)
{
// if the entire entry is before the kernel, continue
if (entry.addr + entry.len <= minAddr)
left.numPages += right.numPages;
right.numPages = 0;
}
}
std::erase_if(ranges, [](const baos::MemoryRange& range)
{
addr += sizeof(entry.size) + entry.size;
continue;
}
// otherwise shrink it and use the rest
entry.len -= (minAddr - entry.addr);
entry.addr = minAddr;
}
__ba_registerAllocatableMemory(reinterpret_cast<void*>(entry.addr), entry.len);
}
addr += sizeof(entry.size) + entry.size;
}
#endif
return range.numPages == 0;
});
return ranges;
}
using initfunc_t = void *();
@ -161,6 +170,21 @@ void setupInterrupt(std::uint8_t index, THandler handler) noexcept
.offsetHigh = (offset >> 16)
};
}
void initializePCIDevice(const baos::pci::Header& header) noexcept
{
using namespace baos;
switch (header.baseClass)
{
case pci::BaseClass::SERIAL_BUS_CONTROLLER:
switch (header.subClass)
{
case pci::SubClass::USB_CONTROLLER:
(void) usb::initController(header); // TODO: print something on error?
break;
}
}
}
}
extern "C"
@ -210,6 +234,11 @@ void kernel_main()
initGlobals();
// init the heap (required for the double buffer)
const std::vector<MemoryRange> ranges = detectMemoryRangesFromEfi(gBootInfo->memoryMap);
setupPaging({ranges.begin(), ranges.end()}); // TODO: move this up when it's done
identityMapRegion(gBootInfo, sizeof(*gBootInfo));
identityMapRegion(gBootInfo->displayInfo.frameBufferBase, gBootInfo->displayInfo.frameBufferPitch * gBootInfo->displayInfo.frameBufferHeight);
// initHeapFromEfiMemoryMap(gBootInfo->memoryMap);
// initialize the framebuffer
@ -223,6 +252,11 @@ void kernel_main()
// initialize terminal interface
tty::initialize();
for (const MemoryRange& range : ranges)
{
std::printf("Start: 0x%lX, Pages: %ld, Type: %s\n", range.pageBase << 12, range.numPages, memoryTypeName(range.type));
}
if (!initSerialPort(PORT_COM1))
{
tty::write("Error initializing serial port.\n");
@ -242,6 +276,11 @@ void kernel_main()
return;
}
for (const pci::Header header : pci::enumerateDevices())
{
initializePCIDevice(header);
}
std::puts("This is BadAppleOS and everything is fine!\n");
// __enterUsermode(SEGIDX_USER_CODE, SEGIDX_USER_DATA, &tss.rsp0, &main);