Compare commits

...

6 Commits

Author SHA1 Message Date
Bananymous 00ee86920a Kernel: Add timeout to ACHI commands
ACHI commands can now fail from timeouts.
2023-10-24 11:56:25 +03:00
Bananymous 51ad27ea3c BuildSystem: Match README.md with the new buildsystem 2023-10-24 11:56:00 +03:00
Bananymous df69612bb1 BuildSystem: Rewrite whole build system structure
Now you have to use script/build.sh for building and running banan-os
2023-10-24 11:56:00 +03:00
Bananymous 5bfeb9f3ca Kernel: Rewrite all read/write functions to use BAN::ByteSpan
This allows us to not work with raw pointers and use sized containers
for reading and writing.
2023-10-24 11:56:00 +03:00
Bananymous db5c24b2a5 BAN: Implement ByteSpan
This is a span over exisiting containers/data types. I'm not too
happy with the constructors and assignment operators, but they will
work for now
2023-10-20 04:59:29 +03:00
Bananymous 781c950af6 BAN: add helper to cast Span<T> to Span<const T> 2023-10-20 04:59:08 +03:00
54 changed files with 699 additions and 405 deletions

121
BAN/include/BAN/ByteSpan.h Normal file
View File

@ -0,0 +1,121 @@
#pragma once
#include <BAN/Span.h>
namespace BAN
{
template<bool CONST>
class ByteSpanGeneral
{
public:
using value_type = maybe_const_t<CONST, uint8_t>;
using size_type = size_t;
public:
ByteSpanGeneral() = default;
ByteSpanGeneral(value_type* data, size_type size)
: m_data(data)
, m_size(size)
{ }
ByteSpanGeneral(ByteSpanGeneral& other)
: m_data(other.data())
, m_size(other.size())
{ }
template<bool C2>
ByteSpanGeneral(const ByteSpanGeneral<C2>& other) requires(CONST)
: m_data(other.data())
, m_size(other.size())
{ }
ByteSpanGeneral(Span<uint8_t> other)
: m_data(other.data())
, m_size(other.size())
{ }
ByteSpanGeneral(const Span<const uint8_t>& other) requires(CONST)
: m_data(other.data())
, m_size(other.size())
{ }
ByteSpanGeneral& operator=(ByteSpanGeneral other)
{
m_data = other.data();
m_size = other.size();
return *this;
}
template<bool C2>
ByteSpanGeneral& operator=(const ByteSpanGeneral<C2>& other) requires(CONST)
{
m_data = other.data();
m_size = other.size();
return *this;
}
ByteSpanGeneral& operator=(Span<uint8_t> other)
{
m_data = other.data();
m_size = other.size();
return *this;
}
ByteSpanGeneral& operator=(const Span<const uint8_t>& other) requires(CONST)
{
m_data = other.data();
m_size = other.size();
return *this;
}
template<typename S>
requires(CONST || !is_const_v<S>)
static ByteSpanGeneral from(S& value)
{
return ByteSpanGeneral(reinterpret_cast<value_type*>(&value), sizeof(S));
}
template<typename S>
requires(!CONST && !is_const_v<S>)
S& as()
{
ASSERT(m_data);
ASSERT(m_size >= sizeof(S));
return *reinterpret_cast<S*>(m_data);
}
template<typename S>
const S& as() const
{
ASSERT(m_data);
ASSERT(m_size >= sizeof(S));
return *reinterpret_cast<S*>(m_data);
}
ByteSpanGeneral slice(size_type offset, size_type length)
{
ASSERT(m_data);
ASSERT(m_size >= offset + length);
return ByteSpanGeneral(m_data + offset, length);
}
value_type& operator[](size_type offset)
{
ASSERT(offset < m_size);
return m_data[offset];
}
const value_type& operator[](size_type offset) const
{
ASSERT(offset < m_size);
return m_data[offset];
}
value_type* data() { return m_data; }
const value_type* data() const { return m_data; }
size_type size() const { return m_size; }
private:
value_type* m_data { nullptr };
size_type m_size { 0 };
};
using ByteSpan = ByteSpanGeneral<false>;
using ConstByteSpan = ByteSpanGeneral<true>;
}

View File

@ -43,6 +43,8 @@ namespace BAN
Span slice(size_type, size_type = ~size_type(0));
Span<const T> as_const() const { return Span<const T>(m_data, m_size); }
private:
T* m_data = nullptr;
size_type m_size = 0;

View File

@ -1,35 +1,13 @@
cmake_minimum_required(VERSION 3.26)
if(DEFINED ENV{BANAN_ARCH})
set(BANAN_ARCH $ENV{BANAN_ARCH})
else()
set(BANAN_ARCH x86_64)
endif()
set(TOOLCHAIN_PREFIX ${CMAKE_SOURCE_DIR}/toolchain/local)
if(EXISTS ${TOOLCHAIN_PREFIX}/bin/${BANAN_ARCH}-banan_os-g++)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}/bin/${BANAN_ARCH}-banan_os-g++)
set(CMAKE_CXX_COMPILER_WORKS True)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}/bin/${BANAN_ARCH}-banan_os-gcc)
set(CMAKE_C_COMPILER_WORKS True)
endif()
if(DEFINED QEMU_ACCEL)
set(QEMU_ACCEL -accel ${QEMU_ACCEL})
endif()
if(DEFINED UEFI_BOOT)
set(UEFI_BOOT 1)
endif()
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "banan-os")
message(FATAL_ERROR "CMAKE_SYSTEM_NAME is not banan-os")
endif ()
add_compile_options(-mno-sse -mno-sse2)
add_compile_definitions(__enable_sse=0)
project(banan-os CXX)
project(banan-os CXX C ASM)
set(BANAN_BASE_SYSROOT ${CMAKE_SOURCE_DIR}/base-sysroot.tar.gz)
set(BANAN_SYSROOT ${CMAKE_BINARY_DIR}/sysroot)
@ -37,7 +15,6 @@ set(BANAN_INCLUDE ${BANAN_SYSROOT}/usr/include)
set(BANAN_LIB ${BANAN_SYSROOT}/usr/lib)
set(BANAN_BIN ${BANAN_SYSROOT}/usr/bin)
set(BANAN_BOOT ${BANAN_SYSROOT}/boot)
set(DISK_IMAGE_PATH ${CMAKE_BINARY_DIR}/banan-os.img)
add_subdirectory(kernel)
add_subdirectory(BAN)
@ -58,63 +35,10 @@ add_custom_target(headers
DEPENDS libelf-headers
)
add_custom_target(toolchain
COMMAND ${CMAKE_COMMAND} -E env SYSROOT="${BANAN_SYSROOT}" PREFIX="${TOOLCHAIN_PREFIX}" ARCH="${BANAN_ARCH}" ${CMAKE_SOURCE_DIR}/toolchain/build.sh
DEPENDS headers
USES_TERMINAL
)
add_custom_target(libstdc++
COMMAND ${CMAKE_COMMAND} -E env LIBSTDCPP="1" ${CMAKE_SOURCE_DIR}/toolchain/build.sh
DEPENDS libc-install
USES_TERMINAL
)
add_custom_target(image
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
add_custom_target(install-sysroot
DEPENDS kernel-install
DEPENDS ban-install
DEPENDS libc-install
DEPENDS userspace-install
DEPENDS libelf-install
USES_TERMINAL
)
add_custom_target(image-full
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 ban-install
DEPENDS libc-install
DEPENDS userspace-install
DEPENDS libelf-install
USES_TERMINAL
)
add_custom_target(check-fs
COMMAND ${CMAKE_COMMAND} -E env DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" ${CMAKE_SOURCE_DIR}/check-fs.sh
USES_TERMINAL
)
add_custom_target(qemu
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
USES_TERMINAL
)
add_custom_target(qemu-nographic
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
USES_TERMINAL
)
add_custom_target(qemu-debug
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
USES_TERMINAL
)
add_custom_target(bochs
COMMAND ${CMAKE_COMMAND} -E env DISK_IMAGE_PATH="${DISK_IMAGE_PATH}" ${CMAKE_SOURCE_DIR}/bochs.sh
DEPENDS image
USES_TERMINAL
)

View File

@ -62,7 +62,7 @@ namespace LibELF
return BAN::Error::from_errno(ENOEXEC);
}
size_t nread = TRY(m_inode->read(0, &m_file_header, sizeof(m_file_header)));
size_t nread = TRY(m_inode->read(0, BAN::ByteSpan::from(m_file_header)));
ASSERT(nread == sizeof(m_file_header));
if (m_file_header.e_ident[EI_MAG0] != ELFMAG0 ||
@ -113,7 +113,7 @@ namespace LibELF
TRY(m_program_headers.resize(m_file_header.e_phnum));
for (size_t i = 0; i < m_file_header.e_phnum; i++)
{
TRY(m_inode->read(m_file_header.e_phoff + m_file_header.e_phentsize * i, &m_program_headers[i], m_file_header.e_phentsize));
TRY(m_inode->read(m_file_header.e_phoff + m_file_header.e_phentsize * i, BAN::ByteSpan::from(m_program_headers[i])));
const auto& pheader = m_program_headers[i];
if (pheader.p_type != PT_NULL && pheader.p_type != PT_LOAD)
@ -242,7 +242,7 @@ namespace LibELF
file_offset = vaddr - program_header.p_vaddr;
size_t bytes = BAN::Math::min<size_t>(PAGE_SIZE - vaddr_offset, program_header.p_filesz - file_offset);
TRY(m_inode->read(program_header.p_offset + file_offset, (void*)(vaddr + vaddr_offset), bytes));
TRY(m_inode->read(program_header.p_offset + file_offset, { (uint8_t*)vaddr + vaddr_offset, bytes }));
}
return {};

View File

@ -1 +0,0 @@
set(CMAKE_GENERATOR "Ninja" CACHE INTERNAL "" FORCE)

View File

@ -2,7 +2,7 @@
# banan-os
This is my hobby operating system written in C++. Currently supports only x86_64 architecture. We have a read-only ext2 filesystem, read-write ramfs, IDE disk drivers in ATA PIO mode, userspace processes, executable loading from ELF format, linear VBE graphics and multithreaded processing on single core.
This is my hobby operating system written in C++. Currently supports only x86_64 architecture. We have a read-only ext2 filesystem, read-write ramfs, IDE disk drivers in ATA PIO mode, ATA AHCI drivers, userspace processes, executable loading from ELF format, linear VBE graphics and multithreaded processing on single core.
![screenshot from qemu running banan-os](assets/banan-os.png)
@ -14,41 +14,32 @@ Each major component and library has its own subdirectory (kernel, userspace, li
There does not exist a complete list of needed packages for building. From the top of my head I can say that *cmake*, *ninja*, *make*, *grub*, *rsync* and emulator (*qemu* or *bochs*) are needed.
You can and *should* pass cmake variable QEMU_ACCEL set to proper accelerator to cmake commands. For example on Linux this means adding -DQEMU_ACCEL=kvm to the end of all cmake commands.
Create the build directory and cofigure cmake
```sh
mkdir build
cd build
cmake ..
```
To build the toolchain for this os. You can run the following command.
> ***NOTE:*** The following step has to be done only once. This might take a long time since we are compiling binutils and gcc.
```sh
ninja toolchain
cmake --fresh .. # We need to reconfigure cmake to use the new compiler
ninja libstdc++
./script/build.sh toolchain
```
To build the os itself you can run either of the following commands. You will need root access since the sysroot has "proper" permissions.
To build the os itself you can run one of the following commands. You will need root access since the sysroot has "proper" permissions.
```sh
ninja qemu
ninja bochs
./script/build.sh qemu
./script/build.sh qemu-nographic
./script/build.sh qemu-debug
./script/build.sh bochs
```
You can also build the kernel or disk image without running it:
```sh
ninja kernel
ninja image
./script/build.sh kernel
./script/build.sh image
```
If you have corrupted your disk image or want to create new one, you can either manually delete *banan-os.img* and cmake will automatically create you a new one or you can run the following command.
If you have corrupted your disk image or want to create new one, you can either manually delete *build/banan-os.img* and build system will automatically create you a new one or you can run the following command.
```sh
ninja image-full
./script/build.sh image-full
```
> ***NOTE*** ```ninja clean``` has to be ran with root permissions, since it deletes the root filesystem.
> ***NOTE*** ```ninja clean``` has to be ran with root permissions, since it deletes from the banan-so sysroot.
### Contributing

View File

@ -1,10 +0,0 @@
#!/bin/bash
set -e
LOOP_DEV=$(sudo losetup -f --show $DISK_IMAGE_PATH)
sudo partprobe $LOOP_DEV
sudo fsck.ext2 -fn ${LOOP_DEV}p2 || true
sudo losetup -d $LOOP_DEV

View File

@ -1,30 +0,0 @@
#!/bin/bash
if [ ! -f $DISK_IMAGE_PATH ]; then
$(dirname "$0")/image-full.sh
exit 0
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
LOOP_DEV=$(sudo losetup -f --show $DISK_IMAGE_PATH)
sudo partprobe $LOOP_DEV
ROOT_PARTITON=${LOOP_DEV}p2
sudo mount $ROOT_PARTITON $MOUNT_DIR
sudo rsync -a ${SYSROOT}/* ${MOUNT_DIR}/
sudo umount $MOUNT_DIR
sudo losetup -d $LOOP_DEV

View File

@ -20,8 +20,8 @@ namespace Kernel
, m_rdev(rdev)
{ }
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override { return 0; }
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t size) override { return size; };
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return 0; }
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return buffer.size(); };
private:
const dev_t m_rdev;

View File

@ -18,8 +18,8 @@ namespace Kernel
, m_rdev(rdev)
{ }
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 size) override { return size; };
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return buffer.size(); };
private:
const dev_t m_rdev;

View File

@ -33,6 +33,9 @@ namespace Kernel
uint8_t* data() { return m_buffer.data(); }
const uint8_t* data() const { return m_buffer.data(); }
BAN::ByteSpan span() { return m_buffer; }
BAN::ConstByteSpan span() const { return m_buffer.as_const(); }
uint8_t& operator[](size_t index) { return m_buffer[index]; }
uint8_t operator[](size_t index) const { return m_buffer[index]; }

View File

@ -34,8 +34,8 @@ namespace Kernel
virtual BAN::ErrorOr<BAN::String> link_target_impl() 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> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
private:

View File

@ -1,10 +1,11 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/RefPtr.h>
#include <BAN/String.h>
#include <BAN/StringView.h>
#include <BAN/WeakPtr.h>
#include <BAN/Vector.h>
#include <BAN/WeakPtr.h>
#include <kernel/API/DirectoryEntry.h>
#include <kernel/Credentials.h>
@ -95,8 +96,8 @@ namespace Kernel
BAN::ErrorOr<BAN::String> link_target();
// General API
BAN::ErrorOr<size_t> read(off_t, void*, size_t);
BAN::ErrorOr<size_t> write(off_t, const void*, size_t);
BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer);
BAN::ErrorOr<size_t> write(off_t, BAN::ConstByteSpan buffer);
BAN::ErrorOr<void> truncate(size_t);
bool has_data() const;
@ -111,8 +112,8 @@ namespace Kernel
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
// General API
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual bool has_data_impl() const { dwarnln("nonblock not supported"); return true; }

View File

@ -31,8 +31,8 @@ namespace Kernel
virtual dev_t rdev() const override { return 0; } // FIXME
protected:
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> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
private:
Pipe(const Credentials&);

View File

@ -23,23 +23,23 @@ namespace Kernel
class ProcROInode final : public RamInode
{
public:
static BAN::ErrorOr<BAN::RefPtr<ProcROInode>> create(Process&, size_t (Process::*callback)(off_t, void*, size_t) const, RamFileSystem&, mode_t, uid_t, gid_t);
static BAN::ErrorOr<BAN::RefPtr<ProcROInode>> create(Process&, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, RamFileSystem&, mode_t, uid_t, gid_t);
~ProcROInode() = default;
protected:
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
// You may not write here and this is always non blocking
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override { return BAN::Error::from_errno(EINVAL); }
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(EINVAL); }
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); }
virtual bool has_data_impl() const override { return true; }
private:
ProcROInode(Process&, size_t (Process::*)(off_t, void*, size_t) const, RamFileSystem&, const FullInodeInfo&);
ProcROInode(Process&, size_t (Process::*)(off_t, BAN::ByteSpan) const, RamFileSystem&, const FullInodeInfo&);
private:
Process& m_process;
size_t (Process::*m_callback)(off_t, void*, size_t) const;
size_t (Process::*m_callback)(off_t, BAN::ByteSpan) const;
};
}

View File

@ -70,8 +70,8 @@ namespace Kernel
protected:
RamFileInode(RamFileSystem&, const FullInodeInfo&);
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> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
private:

View File

@ -63,7 +63,7 @@ namespace Kernel::Input
virtual dev_t rdev() const override { return m_rdev; }
protected:
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
private:
const dev_t m_rdev;

View File

@ -41,8 +41,8 @@ namespace Kernel
void close_all();
void close_cloexec();
BAN::ErrorOr<size_t> read(int fd, void* buffer, size_t count);
BAN::ErrorOr<size_t> write(int fd, const void* buffer, size_t count);
BAN::ErrorOr<size_t> read(int fd, BAN::ByteSpan);
BAN::ErrorOr<size_t> write(int fd, BAN::ConstByteSpan);
BAN::ErrorOr<void> read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size);

View File

@ -139,9 +139,9 @@ namespace Kernel
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); }
size_t proc_meminfo(off_t offset, void* buffer, size_t buffer_size) const;
size_t proc_cmdline(off_t offset, void* buffer, size_t buffer_size) const;
size_t proc_environ(off_t offset, void* buffer, size_t buffer_size) const;
size_t proc_meminfo(off_t offset, BAN::ByteSpan) const;
size_t proc_cmdline(off_t offset, BAN::ByteSpan) const;
size_t proc_environ(off_t offset, BAN::ByteSpan) const;
bool is_userspace() const { return m_is_userspace; }
const userspace_info_t& userspace_info() const { return m_userspace_info; }

View File

@ -23,14 +23,15 @@ namespace Kernel
BAN::ErrorOr<void> rebase();
BAN::ErrorOr<void> read_identify_data();
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t lba, uint64_t sector_count, uint8_t* buffer) override;
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t lba, uint64_t sector_count, const uint8_t* buffer) override;
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan) override;
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan) override;
BAN::ErrorOr<void> send_command_and_block(uint64_t lba, uint64_t sector_count, Command command);
BAN::Optional<uint32_t> find_free_command_slot();
void handle_irq();
void block_until_irq();
BAN::ErrorOr<void> block_until_command_completed(uint32_t command_slot);
private:
BAN::RefPtr<AHCIController> m_controller;
@ -41,8 +42,6 @@ namespace Kernel
// TODO: can we read straight to user buffer?
BAN::UniqPtr<DMARegion> m_data_dma_region;
volatile bool m_has_got_irq { false };
friend class AHCIController;
};

View File

@ -1,5 +1,6 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/RefPtr.h>
#include <BAN/Vector.h>
#include <kernel/InterruptController.h>
@ -22,8 +23,8 @@ namespace Kernel
public:
static BAN::ErrorOr<BAN::RefPtr<ATABus>> create(uint16_t base, uint16_t ctrl, uint8_t irq);
BAN::ErrorOr<void> read(ATADevice&, uint64_t, uint8_t, uint8_t*);
BAN::ErrorOr<void> write(ATADevice&, uint64_t, uint8_t, const uint8_t*);
BAN::ErrorOr<void> read(ATADevice&, uint64_t lba, uint64_t sector_count, BAN::ByteSpan);
BAN::ErrorOr<void> write(ATADevice&, uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan);
virtual void handle_irq() override;

View File

@ -32,8 +32,8 @@ namespace Kernel
virtual dev_t rdev() const override { return m_rdev; }
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> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
protected:
ATABaseDevice();
@ -63,8 +63,8 @@ namespace Kernel
private:
ATADevice(BAN::RefPtr<ATABus>, ATABus::DeviceType, bool is_secodary);
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t, uint64_t, uint8_t*) override;
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t, uint64_t, const uint8_t*) override;
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t, uint64_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t, uint64_t, BAN::ConstByteSpan) override;
private:
BAN::RefPtr<ATABus> m_bus;

View File

@ -1,6 +1,7 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/ByteSpan.h>
#include <kernel/Memory/Types.h>
#include <kernel/SpinLock.h>
@ -15,8 +16,8 @@ namespace Kernel
DiskCache(size_t sector_size, StorageDevice&);
~DiskCache();
bool read_from_cache(uint64_t sector, uint8_t* buffer);
BAN::ErrorOr<void> write_to_cache(uint64_t sector, const uint8_t* buffer, bool dirty);
bool read_from_cache(uint64_t sector, BAN::ByteSpan);
BAN::ErrorOr<void> write_to_cache(uint64_t sector, BAN::ConstByteSpan, bool dirty);
BAN::ErrorOr<void> sync();
size_t release_clean_pages(size_t);

View File

@ -30,8 +30,8 @@ namespace Kernel
const char* label() const { return m_label; }
const StorageDevice& device() const { return m_device; }
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer);
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer);
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint8_t sector_count, BAN::ByteSpan);
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint8_t sector_count, BAN::ConstByteSpan);
virtual BAN::StringView name() const override { return m_name; }
@ -57,7 +57,7 @@ namespace Kernel
virtual dev_t rdev() const override { return m_rdev; }
protected:
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
private:
const dev_t m_rdev;
@ -73,8 +73,8 @@ namespace Kernel
BAN::ErrorOr<void> initialize_partitions();
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint64_t sector_count, uint8_t* buffer);
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint64_t sector_count, const uint8_t* buffer);
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint64_t sector_count, BAN::ByteSpan);
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan);
virtual uint32_t sector_size() const = 0;
virtual uint64_t total_size() const = 0;
@ -86,8 +86,8 @@ namespace Kernel
virtual bool is_storage_device() const override { return true; }
protected:
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t lba, uint64_t sector_count, uint8_t* buffer) = 0;
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t lba, uint64_t sector_count, const uint8_t* buffer) = 0;
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan) = 0;
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan) = 0;
void add_disk_cache();
private:

View File

@ -49,8 +49,8 @@ namespace Kernel
{ }
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> write_impl(off_t, const void*, size_t) override;
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
private:
void do_backspace();

View File

@ -12,10 +12,10 @@ namespace Kernel
return BAN::RefPtr<ZeroDevice>::adopt(result);
}
BAN::ErrorOr<size_t> ZeroDevice::read_impl(off_t, void* buffer, size_t bytes)
BAN::ErrorOr<size_t> ZeroDevice::read_impl(off_t, BAN::ByteSpan buffer)
{
memset(buffer, 0, bytes);
return bytes;
memset(buffer.data(), 0, buffer.size());
return buffer.size();
}
}

View File

@ -33,7 +33,7 @@ namespace Kernel
BAN::Vector<uint8_t> superblock_buffer;
TRY(superblock_buffer.resize(sector_count * sector_size));
TRY(m_partition.read_sectors(lba, sector_count, superblock_buffer.data()));
TRY(m_partition.read_sectors(lba, sector_count, superblock_buffer.span()));
memcpy(&m_superblock, superblock_buffer.data(), sizeof(Ext2::Superblock));
}
@ -223,7 +223,7 @@ namespace Kernel
ASSERT(block >= 2);
ASSERT(buffer.size() >= block_size);
MUST(m_partition.read_sectors(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.data()));
MUST(m_partition.read_sectors(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.span()));
}
void Ext2FS::write_block(uint32_t block, const BlockBufferWrapper& buffer)
@ -237,7 +237,7 @@ namespace Kernel
ASSERT(block >= 2);
ASSERT(buffer.size() >= block_size);
MUST(m_partition.write_sectors(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.data()));
MUST(m_partition.write_sectors(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.span()));
}
void Ext2FS::sync_superblock()
@ -258,11 +258,11 @@ namespace Kernel
BAN::Vector<uint8_t> superblock_buffer;
MUST(superblock_buffer.resize(sector_count * sector_size));
MUST(m_partition.read_sectors(lba, sector_count, superblock_buffer.data()));
MUST(m_partition.read_sectors(lba, sector_count, superblock_buffer.span()));
if (memcmp(superblock_buffer.data(), &m_superblock, superblock_bytes))
{
memcpy(superblock_buffer.data(), &m_superblock, superblock_bytes);
MUST(m_partition.write_sectors(lba, sector_count, superblock_buffer.data()));
MUST(m_partition.write_sectors(lba, sector_count, superblock_buffer.span()));
}
}

View File

@ -100,19 +100,21 @@ namespace Kernel
return BAN::Error::from_errno(ENOTSUP);
}
BAN::ErrorOr<size_t> Ext2Inode::read_impl(off_t offset, void* buffer, size_t count)
BAN::ErrorOr<size_t> Ext2Inode::read_impl(off_t offset, BAN::ByteSpan buffer)
{
// FIXME: update atime if needed
ASSERT(!mode().ifdir());
ASSERT(offset >= 0);
if (offset >= UINT32_MAX || count >= UINT32_MAX || offset + count >= UINT32_MAX)
if (offset >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
return BAN::Error::from_errno(EOVERFLOW);
if (offset >= m_inode.size)
return 0;
if (offset + count > m_inode.size)
uint32_t count = buffer.size();
if (offset + buffer.size() > m_inode.size)
count = m_inode.size - offset;
const uint32_t block_size = blksize();
@ -131,7 +133,7 @@ namespace Kernel
uint32_t copy_offset = (offset + n_read) % block_size;
uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - copy_offset, count - n_read);
memcpy((uint8_t*)buffer + n_read, block_buffer.data() + copy_offset, to_copy);
memcpy(buffer.data() + n_read, block_buffer.data() + copy_offset, to_copy);
n_read += to_copy;
}
@ -139,26 +141,25 @@ namespace Kernel
return n_read;
}
BAN::ErrorOr<size_t> Ext2Inode::write_impl(off_t offset, const void* buffer, size_t count)
BAN::ErrorOr<size_t> Ext2Inode::write_impl(off_t offset, BAN::ConstByteSpan buffer)
{
// FIXME: update atime if needed
ASSERT(!mode().ifdir());
ASSERT(offset >= 0);
if (offset >= UINT32_MAX || count >= UINT32_MAX || offset + count >= UINT32_MAX)
if (offset >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
return BAN::Error::from_errno(EOVERFLOW);
if (m_inode.size < offset + count)
TRY(truncate_impl(offset + count));
if (m_inode.size < offset + buffer.size())
TRY(truncate_impl(offset + buffer.size()));
const uint32_t block_size = blksize();
auto block_buffer = m_fs.get_block_buffer();
const uint8_t* u8buffer = (const uint8_t*)buffer;
size_t to_write = count;
size_t written = 0;
size_t to_write = buffer.size();
// Write partial block
if (offset % block_size)
@ -169,10 +170,10 @@ namespace Kernel
uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - block_offset, to_write);
m_fs.read_block(block_index, block_buffer);
memcpy(block_buffer.data() + block_offset, u8buffer, to_copy);
memcpy(block_buffer.data() + block_offset, buffer.data(), to_copy);
m_fs.write_block(block_index, block_buffer);
u8buffer += to_copy;
written += to_copy;
offset += to_copy;
to_write -= to_copy;
}
@ -181,10 +182,10 @@ namespace Kernel
{
uint32_t block_index = fs_block_of_data_block_index(offset / block_size);
memcpy(block_buffer.data(), u8buffer, block_buffer.size());
memcpy(block_buffer.data(), buffer.data() + written, block_buffer.size());
m_fs.write_block(block_index, block_buffer);
u8buffer += block_size;
written += block_size;
offset += block_size;
to_write -= block_size;
}
@ -194,11 +195,11 @@ namespace Kernel
uint32_t block_index = fs_block_of_data_block_index(offset / block_size);
m_fs.read_block(block_index, block_buffer);
memcpy(block_buffer.data(), u8buffer, to_write);
memcpy(block_buffer.data(), buffer.data() + written, to_write);
m_fs.write_block(block_index, block_buffer);
}
return count;
return buffer.size();
}
BAN::ErrorOr<void> Ext2Inode::truncate_impl(size_t new_size)

View File

@ -102,22 +102,22 @@ namespace Kernel
return link_target_impl();
}
BAN::ErrorOr<size_t> Inode::read(off_t offset, void* buffer, size_t bytes)
BAN::ErrorOr<size_t> Inode::read(off_t offset, BAN::ByteSpan buffer)
{
LockGuard _(m_lock);
Thread::TerminateBlocker blocker(Thread::current());
if (mode().ifdir())
return BAN::Error::from_errno(EISDIR);
return read_impl(offset, buffer, bytes);
return read_impl(offset, buffer);
}
BAN::ErrorOr<size_t> Inode::write(off_t offset, const void* buffer, size_t bytes)
BAN::ErrorOr<size_t> Inode::write(off_t offset, BAN::ConstByteSpan buffer)
{
LockGuard _(m_lock);
Thread::TerminateBlocker blocker(Thread::current());
if (mode().ifdir())
return BAN::Error::from_errno(EISDIR);
return write_impl(offset, buffer, bytes);
return write_impl(offset, buffer);
}
BAN::ErrorOr<void> Inode::truncate(size_t size)

View File

@ -39,7 +39,7 @@ namespace Kernel
m_semaphore.unblock();
}
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, void* buffer, size_t count)
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, BAN::ByteSpan buffer)
{
LockGuard _(m_lock);
while (m_buffer.empty())
@ -51,8 +51,8 @@ namespace Kernel
m_lock.lock();
}
size_t to_copy = BAN::Math::min<size_t>(count, m_buffer.size());
memcpy(buffer, m_buffer.data(), to_copy);
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer.size());
memcpy(buffer.data(), m_buffer.data(), to_copy);
memmove(m_buffer.data(), m_buffer.data() + to_copy, m_buffer.size() - to_copy);
MUST(m_buffer.resize(m_buffer.size() - to_copy));
@ -64,14 +64,14 @@ namespace Kernel
return to_copy;
}
BAN::ErrorOr<size_t> Pipe::write_impl(off_t, const void* buffer, size_t count)
BAN::ErrorOr<size_t> Pipe::write_impl(off_t, BAN::ConstByteSpan buffer)
{
LockGuard _(m_lock);
size_t old_size = m_buffer.size();
TRY(m_buffer.resize(old_size + count));
memcpy(m_buffer.data() + old_size, buffer, count);
TRY(m_buffer.resize(old_size + buffer.size()));
memcpy(m_buffer.data() + old_size, buffer.data(), buffer.size());
timespec current_time = SystemTimer::get().real_time();
m_mtime = current_time;
@ -79,7 +79,7 @@ namespace Kernel
m_semaphore.unblock();
return count;
return buffer.size();
}
}

View File

@ -25,7 +25,7 @@ namespace Kernel
{
}
BAN::ErrorOr<BAN::RefPtr<ProcROInode>> ProcROInode::create(Process& process, size_t (Process::*callback)(off_t, void*, size_t) const, RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
BAN::ErrorOr<BAN::RefPtr<ProcROInode>> ProcROInode::create(Process& process, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
{
FullInodeInfo inode_info(fs, mode, uid, gid);
@ -35,7 +35,7 @@ namespace Kernel
return BAN::RefPtr<ProcROInode>::adopt(inode_ptr);
}
ProcROInode::ProcROInode(Process& process, size_t (Process::*callback)(off_t, void*, size_t) const, RamFileSystem& fs, const FullInodeInfo& inode_info)
ProcROInode::ProcROInode(Process& process, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, RamFileSystem& fs, const FullInodeInfo& inode_info)
: RamInode(fs, inode_info)
, m_process(process)
, m_callback(callback)
@ -43,12 +43,12 @@ namespace Kernel
m_inode_info.mode |= Inode::Mode::IFREG;
}
BAN::ErrorOr<size_t> ProcROInode::read_impl(off_t offset, void* buffer, size_t buffer_size)
BAN::ErrorOr<size_t> ProcROInode::read_impl(off_t offset, BAN::ByteSpan buffer)
{
ASSERT(offset >= 0);
if ((size_t)offset >= sizeof(proc_meminfo_t))
return 0;
return (m_process.*m_callback)(offset, buffer, buffer_size);
return (m_process.*m_callback)(offset, buffer);
}
}

View File

@ -48,23 +48,23 @@ namespace Kernel
m_inode_info.mode |= Inode::Mode::IFREG;
}
BAN::ErrorOr<size_t> RamFileInode::read_impl(off_t offset, void* buffer, size_t bytes)
BAN::ErrorOr<size_t> RamFileInode::read_impl(off_t offset, BAN::ByteSpan buffer)
{
ASSERT(offset >= 0);
if (offset >= size())
return 0;
size_t to_copy = BAN::Math::min<size_t>(m_inode_info.size - offset, bytes);
memcpy(buffer, m_data.data(), to_copy);
size_t to_copy = BAN::Math::min<size_t>(m_inode_info.size - offset, buffer.size());
memcpy(buffer.data(), m_data.data(), to_copy);
return to_copy;
}
BAN::ErrorOr<size_t> RamFileInode::write_impl(off_t offset, const void* buffer, size_t bytes)
BAN::ErrorOr<size_t> RamFileInode::write_impl(off_t offset, BAN::ConstByteSpan buffer)
{
ASSERT(offset >= 0);
if (offset + bytes > (size_t)size())
TRY(truncate_impl(offset + bytes));
memcpy(m_data.data() + offset, buffer, bytes);
return bytes;
if (offset + buffer.size() > (size_t)size())
TRY(truncate_impl(offset + buffer.size()));
memcpy(m_data.data() + offset, buffer.data(), buffer.size());
return buffer.size();
}
BAN::ErrorOr<void> RamFileInode::truncate_impl(size_t new_size)

View File

@ -43,7 +43,7 @@ namespace Kernel
BAN::Vector<uint8_t> file_data;
TRY(file_data.resize(inode->size()));
TRY(inode->read(0, file_data.data(), file_data.size()));
TRY(inode->read(0, file_data.span()));
if (file_data.size() < 4)
return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall);

View File

@ -217,9 +217,9 @@ namespace Kernel::Input
append_command_queue(Command::SET_LEDS, new_leds);
}
BAN::ErrorOr<size_t> PS2Keyboard::read_impl(off_t, void* buffer, size_t size)
BAN::ErrorOr<size_t> PS2Keyboard::read_impl(off_t, BAN::ByteSpan buffer)
{
if (size < sizeof(KeyEvent))
if (buffer.size() < sizeof(KeyEvent))
return BAN::Error::from_errno(ENOBUFS);
while (true)
@ -231,7 +231,7 @@ namespace Kernel::Input
if (m_event_queue.empty())
continue;
*(KeyEvent*)buffer = m_event_queue.front();
buffer.as<KeyEvent>() = m_event_queue.front();
m_event_queue.pop();
return sizeof(KeyEvent);

View File

@ -80,7 +80,7 @@ namespace Kernel
page_table.unmap_page(0);
}
if (auto ret = inode->write(i * PAGE_SIZE, page_buffer, PAGE_SIZE); ret.is_error())
if (auto ret = inode->write(i * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer)); ret.is_error())
dwarnln("{}", ret.error());
}
}
@ -109,7 +109,7 @@ namespace Kernel
// Zero out the new page
if (&PageTable::current() == &m_page_table)
read_ret = m_inode->read(file_offset, (void*)vaddr, bytes);
read_ret = m_inode->read(file_offset, BAN::ByteSpan((uint8_t*)vaddr, bytes));
else
{
auto& page_table = PageTable::current();
@ -118,7 +118,7 @@ namespace Kernel
ASSERT(page_table.is_page_free(0));
page_table.map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
read_ret = m_inode->read(file_offset, (void*)0, bytes);
read_ret = m_inode->read(file_offset, BAN::ByteSpan((uint8_t*)0, bytes));
memset((void*)0, 0x00, PAGE_SIZE);
page_table.unmap_page(0);
}
@ -156,7 +156,7 @@ namespace Kernel
size_t offset = vaddr - m_vaddr;
size_t bytes = BAN::Math::min<size_t>(m_size - offset, PAGE_SIZE);
TRY(m_inode->read(offset, m_shared_data->page_buffer, bytes));
TRY(m_inode->read(offset, BAN::ByteSpan(m_shared_data->page_buffer, bytes)));
auto& page_table = PageTable::current();

View File

@ -264,24 +264,24 @@ namespace Kernel
}
}
BAN::ErrorOr<size_t> OpenFileDescriptorSet::read(int fd, void* buffer, size_t count)
BAN::ErrorOr<size_t> OpenFileDescriptorSet::read(int fd, BAN::ByteSpan buffer)
{
TRY(validate_fd(fd));
auto& open_file = m_open_files[fd];
if ((open_file->flags & O_NONBLOCK) && !open_file->inode->has_data())
return 0;
size_t nread = TRY(open_file->inode->read(open_file->offset, buffer, count));
size_t nread = TRY(open_file->inode->read(open_file->offset, buffer));
open_file->offset += nread;
return nread;
}
BAN::ErrorOr<size_t> OpenFileDescriptorSet::write(int fd, const void* buffer, size_t count)
BAN::ErrorOr<size_t> OpenFileDescriptorSet::write(int fd, BAN::ConstByteSpan buffer)
{
TRY(validate_fd(fd));
auto& open_file = m_open_files[fd];
if (open_file->flags & O_APPEND)
open_file->offset = open_file->inode->size();
size_t nwrite = TRY(open_file->inode->write(open_file->offset, buffer, count));
size_t nwrite = TRY(open_file->inode->write(open_file->offset, buffer));
open_file->offset += nwrite;
return nwrite;
}

View File

@ -260,7 +260,7 @@ namespace Kernel
thread->set_terminating();
}
size_t Process::proc_meminfo(off_t offset, void* buffer, size_t buffer_size) const
size_t Process::proc_meminfo(off_t offset, BAN::ByteSpan buffer) const
{
ASSERT(offset >= 0);
if ((size_t)offset >= sizeof(proc_meminfo_t))
@ -290,12 +290,12 @@ namespace Kernel
}
}
size_t bytes = BAN::Math::min<size_t>(sizeof(proc_meminfo_t) - offset, buffer_size);
memcpy(buffer, (uint8_t*)&meminfo + offset, bytes);
size_t bytes = BAN::Math::min<size_t>(sizeof(proc_meminfo_t) - offset, buffer.size());
memcpy(buffer.data(), (uint8_t*)&meminfo + offset, bytes);
return bytes;
}
static size_t read_from_vec_of_str(const BAN::Vector<BAN::String>& container, size_t start, void* buffer, size_t buffer_size)
static size_t read_from_vec_of_str(const BAN::Vector<BAN::String>& container, size_t start, BAN::ByteSpan buffer)
{
size_t offset = 0;
size_t written = 0;
@ -307,11 +307,11 @@ namespace Kernel
if (offset < start)
elem_offset = start - offset;
size_t bytes = BAN::Math::min<size_t>(elem.size() + 1 - elem_offset, buffer_size - written);
memcpy((uint8_t*)buffer + written, elem.data() + elem_offset, bytes);
size_t bytes = BAN::Math::min<size_t>(elem.size() + 1 - elem_offset, buffer.size() - written);
memcpy(buffer.data() + written, elem.data() + elem_offset, bytes);
written += bytes;
if (written >= buffer_size)
if (written >= buffer.size())
break;
}
offset += elem.size() + 1;
@ -319,16 +319,16 @@ namespace Kernel
return written;
}
size_t Process::proc_cmdline(off_t offset, void* buffer, size_t buffer_size) const
size_t Process::proc_cmdline(off_t offset, BAN::ByteSpan buffer) const
{
LockGuard _(m_lock);
return read_from_vec_of_str(m_cmdline, offset, buffer, buffer_size);
return read_from_vec_of_str(m_cmdline, offset, buffer);
}
size_t Process::proc_environ(off_t offset, void* buffer, size_t buffer_size) const
size_t Process::proc_environ(off_t offset, BAN::ByteSpan buffer) const
{
LockGuard _(m_lock);
return read_from_vec_of_str(m_environ, offset, buffer, buffer_size);
return read_from_vec_of_str(m_environ, offset, buffer);
}
BAN::ErrorOr<long> Process::sys_exit(int status)
@ -723,14 +723,14 @@ namespace Kernel
{
LockGuard _(m_lock);
validate_pointer_access(buffer, count);
return TRY(m_open_file_descriptors.read(fd, buffer, count));
return TRY(m_open_file_descriptors.read(fd, BAN::ByteSpan((uint8_t*)buffer, count)));
}
BAN::ErrorOr<long> Process::sys_write(int fd, const void* buffer, size_t count)
{
LockGuard _(m_lock);
validate_pointer_access(buffer, count);
return TRY(m_open_file_descriptors.write(fd, buffer, count));
return TRY(m_open_file_descriptors.write(fd, BAN::ByteSpan((uint8_t*)buffer, count)));
}
BAN::ErrorOr<long> Process::sys_pipe(int fildes[2])

View File

@ -1,3 +1,4 @@
#include <kernel/Scheduler.h>
#include <kernel/Storage/ATA/AHCI/Controller.h>
#include <kernel/Storage/ATA/AHCI/Device.h>
#include <kernel/Storage/ATA/ATADefinitions.h>
@ -40,7 +41,7 @@ namespace Kernel
m_port->ie = 0xFFFFFFFF;
TRY(read_identify_data());
TRY(detail::ATABaseDevice::initialize({ (const uint16_t*)m_data_dma_region->vaddr(), m_data_dma_region->size() }));
TRY(detail::ATABaseDevice::initialize({ (const uint16_t*)m_data_dma_region->vaddr(), m_data_dma_region->size() / sizeof(uint16_t) }));
return {};
}
@ -120,8 +121,7 @@ namespace Kernel
m_port->ci = 1 << slot.value();
// FIXME: timeout
do { block_until_irq(); } while (m_port->ci & (1 << slot.value()));
TRY(block_until_command_completed(slot.value()));
return {};
}
@ -145,41 +145,58 @@ namespace Kernel
void AHCIDevice::handle_irq()
{
ASSERT(!m_has_got_irq);
uint16_t err = m_port->serr & 0xFFFF;
if (err)
print_error(err);
m_has_got_irq = true;
}
void AHCIDevice::block_until_irq()
BAN::ErrorOr<void> AHCIDevice::block_until_command_completed(uint32_t command_slot)
{
while (!__sync_bool_compare_and_swap(&m_has_got_irq, true, false))
__builtin_ia32_pause();
static constexpr uint64_t total_timeout_ms = 5000;
static constexpr uint64_t poll_timeout_ms = 10;
auto start_time = SystemTimer::get().ms_since_boot();
while (start_time + poll_timeout_ms < SystemTimer::get().ns_since_boot())
if (!(m_port->ci & (1 << command_slot)))
return {};
// FIXME: This should actually block once semaphores support blocking with timeout.
// This doesn't allow scheduler to go properly idle.
while (start_time + total_timeout_ms < SystemTimer::get().ns_since_boot())
{
Scheduler::get().reschedule();
if (!(m_port->ci & (1 << command_slot)))
return {};
}
return BAN::Error::from_errno(ETIMEDOUT);
}
BAN::ErrorOr<void> AHCIDevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, uint8_t* buffer)
BAN::ErrorOr<void> AHCIDevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
{
ASSERT(buffer.size() >= sector_count * sector_size());
const size_t sectors_per_page = PAGE_SIZE / sector_size();
for (uint64_t sector_off = 0; sector_off < sector_count; sector_off += sectors_per_page)
{
uint64_t to_read = BAN::Math::min<uint64_t>(sector_count - sector_off, sectors_per_page);
TRY(send_command_and_block(lba + sector_off, to_read, Command::Read));
memcpy(buffer + sector_off * sector_size(), (void*)m_data_dma_region->vaddr(), to_read * sector_size());
memcpy(buffer.data() + sector_off * sector_size(), (void*)m_data_dma_region->vaddr(), to_read * sector_size());
}
return {};
}
BAN::ErrorOr<void> AHCIDevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, const uint8_t* buffer)
BAN::ErrorOr<void> AHCIDevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
{
ASSERT(buffer.size() >= sector_count * sector_size());
const size_t sectors_per_page = PAGE_SIZE / sector_size();
for (uint64_t sector_off = 0; sector_off < sector_count; sector_off += sectors_per_page)
{
uint64_t to_read = BAN::Math::min<uint64_t>(sector_count - sector_off, sectors_per_page);
memcpy((void*)m_data_dma_region->vaddr(), buffer + sector_off * sector_size(), to_read * sector_size());
memcpy((void*)m_data_dma_region->vaddr(), buffer.data() + sector_off * sector_size(), to_read * sector_size());
TRY(send_command_and_block(lba + sector_off, to_read, Command::Write));
}
@ -258,8 +275,7 @@ namespace Kernel
m_port->ci = 1 << slot.value();
// FIXME: timeout
do { block_until_irq(); } while (m_port->ci & (1 << slot.value()));
TRY(block_until_command_completed(slot.value()));
return {};
}

View File

@ -228,8 +228,10 @@ namespace Kernel
return BAN::Error::from_error_code(ErrorCode::None);
}
BAN::ErrorOr<void> ATABus::read(ATADevice& device, uint64_t lba, uint8_t sector_count, uint8_t* buffer)
BAN::ErrorOr<void> ATABus::read(ATADevice& device, uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
{
ASSERT(sector_count <= 0xFF);
ASSERT(buffer.size() >= sector_count * device.sector_size());
if (lba + sector_count > device.sector_count())
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
@ -251,7 +253,7 @@ namespace Kernel
for (uint32_t sector = 0; sector < sector_count; sector++)
{
block_until_irq();
read_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device.words_per_sector(), device.words_per_sector());
read_buffer(ATA_PORT_DATA, (uint16_t*)buffer.data() + sector * device.words_per_sector(), device.words_per_sector());
}
}
else
@ -263,8 +265,10 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> ATABus::write(ATADevice& device, uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
BAN::ErrorOr<void> ATABus::write(ATADevice& device, uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
{
ASSERT(sector_count <= 0xFF);
ASSERT(buffer.size() >= sector_count * device.sector_size());
if (lba + sector_count > device.sector_count())
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
@ -285,7 +289,7 @@ namespace Kernel
for (uint32_t sector = 0; sector < sector_count; sector++)
{
write_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device.words_per_sector(), device.words_per_sector());
write_buffer(ATA_PORT_DATA, (uint16_t*)buffer.data() + sector * device.words_per_sector(), device.words_per_sector());
block_until_irq();
}
}

View File

@ -82,24 +82,24 @@ namespace Kernel
return {};
}
BAN::ErrorOr<size_t> detail::ATABaseDevice::read_impl(off_t offset, void* buffer, size_t bytes)
BAN::ErrorOr<size_t> detail::ATABaseDevice::read_impl(off_t offset, BAN::ByteSpan buffer)
{
if (offset % sector_size())
return BAN::Error::from_errno(EINVAL);
if (bytes % sector_size())
if (buffer.size() % sector_size())
return BAN::Error::from_errno(EINVAL);
TRY(read_sectors(offset / sector_size(), bytes / sector_size(), (uint8_t*)buffer));
return bytes;
TRY(read_sectors(offset / sector_size(), buffer.size() / sector_size(), buffer));
return buffer.size();
}
BAN::ErrorOr<size_t> detail::ATABaseDevice::write_impl(off_t offset, const void* buffer, size_t bytes)
BAN::ErrorOr<size_t> detail::ATABaseDevice::write_impl(off_t offset, BAN::ConstByteSpan buffer)
{
if (offset % sector_size())
return BAN::Error::from_errno(EINVAL);
if (bytes % sector_size())
if (buffer.size() % sector_size())
return BAN::Error::from_errno(EINVAL);
TRY(write_sectors(offset / sector_size(), bytes / sector_size(), (const uint8_t*)buffer));
return bytes;
TRY(write_sectors(offset / sector_size(), buffer.size() / sector_size(), buffer));
return buffer.size();
}
BAN::ErrorOr<BAN::RefPtr<ATADevice>> ATADevice::create(BAN::RefPtr<ATABus> bus, ATABus::DeviceType type, bool is_secondary, BAN::Span<const uint16_t> identify_data)
@ -118,14 +118,16 @@ namespace Kernel
, m_is_secondary(is_secondary)
{ }
BAN::ErrorOr<void> ATADevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, uint8_t* buffer)
BAN::ErrorOr<void> ATADevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
{
ASSERT(buffer.size() >= sector_count * sector_size());
TRY(m_bus->read(*this, lba, sector_count, buffer));
return {};
}
BAN::ErrorOr<void> ATADevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, const uint8_t* buffer)
BAN::ErrorOr<void> ATADevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
{
ASSERT(buffer.size() >= sector_count * sector_size());
TRY(m_bus->write(*this, lba, sector_count, buffer));
return {};
}

View File

@ -24,8 +24,10 @@ namespace Kernel
release_all_pages();
}
bool DiskCache::read_from_cache(uint64_t sector, uint8_t* buffer)
bool DiskCache::read_from_cache(uint64_t sector, BAN::ByteSpan buffer)
{
ASSERT(buffer.size() >= m_sector_size);
uint64_t sectors_per_page = PAGE_SIZE / m_sector_size;
uint64_t page_cache_offset = sector % sectors_per_page;
uint64_t page_cache_start = sector - page_cache_offset;
@ -46,7 +48,7 @@ namespace Kernel
CriticalScope _;
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
memcpy(buffer, (void*)(page_cache_offset * m_sector_size), m_sector_size);
memcpy(buffer.data(), (void*)(page_cache_offset * m_sector_size), m_sector_size);
page_table.unmap_page(0);
return true;
@ -55,8 +57,9 @@ namespace Kernel
return false;
};
BAN::ErrorOr<void> DiskCache::write_to_cache(uint64_t sector, const uint8_t* buffer, bool dirty)
BAN::ErrorOr<void> DiskCache::write_to_cache(uint64_t sector, BAN::ConstByteSpan buffer, bool dirty)
{
ASSERT(buffer.size() >= m_sector_size);
uint64_t sectors_per_page = PAGE_SIZE / m_sector_size;
uint64_t page_cache_offset = sector % sectors_per_page;
uint64_t page_cache_start = sector - page_cache_offset;
@ -80,7 +83,7 @@ namespace Kernel
{
CriticalScope _;
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)(page_cache_offset * m_sector_size), buffer, m_sector_size);
memcpy((void*)(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
page_table.unmap_page(0);
}
@ -110,8 +113,8 @@ namespace Kernel
{
CriticalScope _;
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
memcpy((void*)(page_cache_offset * m_sector_size), buffer, m_sector_size);
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
page_table.unmap_page(0);
}
@ -149,7 +152,8 @@ namespace Kernel
else
{
dprintln_if(DEBUG_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, m_sync_cache.data() + sector_start * m_sector_size));
auto data_slice = m_sync_cache.span().slice(sector_start * m_sector_size, sector_count * m_sector_size);
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, data_slice));
sector_start += sector_count + 1;
sector_count = 0;
}
@ -158,7 +162,8 @@ namespace Kernel
if (sector_count > 0)
{
dprintln_if(DEBUG_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, m_sync_cache.data() + sector_start * m_sector_size));
auto data_slice = m_sync_cache.span().slice(sector_start * m_sector_size, sector_count * m_sector_size);
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, data_slice));
}
cache.dirty_mask = 0;

View File

@ -153,8 +153,10 @@ namespace Kernel
if (total_size() < sizeof(GPTHeader))
return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader);
BAN::Vector<uint8_t> lba1(sector_size());
TRY(read_sectors(1, 1, lba1.data()));
BAN::Vector<uint8_t> lba1;
TRY(lba1.resize(sector_size()));
TRY(read_sectors(1, 1, lba1.span()));
const GPTHeader& header = *(const GPTHeader*)lba1.data();
if (!is_valid_gpt_header(header, sector_size()))
@ -169,7 +171,7 @@ namespace Kernel
BAN::Vector<uint8_t> entry_array;
TRY(entry_array.resize(size));
TRY(read_sectors(header.partition_entry_lba, size / sector_size(), entry_array.data()));
TRY(read_sectors(header.partition_entry_lba, size / sector_size(), entry_array.span()));
if (!is_valid_gpt_crc32(header, lba1, entry_array))
return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader);
@ -226,8 +228,9 @@ namespace Kernel
memcpy(m_label, label, sizeof(m_label));
}
BAN::ErrorOr<void> Partition::read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer)
BAN::ErrorOr<void> Partition::read_sectors(uint64_t lba, uint8_t sector_count, BAN::ByteSpan buffer)
{
ASSERT(buffer.size() >= sector_count * m_device.sector_size());
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
if (lba + sector_count > sectors_in_partition)
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
@ -235,8 +238,9 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> Partition::write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
BAN::ErrorOr<void> Partition::write_sectors(uint64_t lba, uint8_t sector_count, BAN::ConstByteSpan buffer)
{
ASSERT(buffer.size() >= sector_count * m_device.sector_size());
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
if (lba + sector_count > sectors_in_partition)
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
@ -244,23 +248,23 @@ namespace Kernel
return {};
}
BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, void* buffer, size_t bytes)
BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, BAN::ByteSpan buffer)
{
ASSERT(offset >= 0);
if (offset % m_device.sector_size() || bytes % m_device.sector_size())
if (offset % m_device.sector_size() || buffer.size() % m_device.sector_size())
return BAN::Error::from_errno(ENOTSUP);
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
uint32_t lba = offset / m_device.sector_size();
uint32_t sector_count = bytes / m_device.sector_size();
uint32_t sector_count = buffer.size() / m_device.sector_size();
if (lba == sectors_in_partition)
return 0;
if (lba + sector_count > sectors_in_partition)
sector_count = sectors_in_partition - lba;
TRY(read_sectors(lba, sector_count, (uint8_t*)buffer));
TRY(read_sectors(lba, sector_count, buffer));
return sector_count * m_device.sector_size();
}
@ -283,36 +287,51 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> StorageDevice::read_sectors(uint64_t lba, uint64_t sector_count, uint8_t* buffer)
BAN::ErrorOr<void> StorageDevice::read_sectors(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
{
ASSERT(buffer.size() >= sector_count * sector_size());
{
LockGuard _(m_lock);
Thread::TerminateBlocker blocker(Thread::current());
if (!m_disk_cache.has_value())
return read_sectors_impl(lba, sector_count, buffer);
}
for (uint64_t offset = 0; offset < sector_count; offset++)
{
LockGuard _(m_lock);
Thread::TerminateBlocker blocker(Thread::current());
uint8_t* buffer_ptr = buffer + offset * sector_size();
if (m_disk_cache.has_value())
if (m_disk_cache->read_from_cache(lba + offset, buffer_ptr))
continue;
TRY(read_sectors_impl(lba + offset, 1, buffer_ptr));
if (m_disk_cache.has_value())
(void)m_disk_cache->write_to_cache(lba + offset, buffer_ptr, false);
auto sector_buffer = buffer.slice(offset * sector_size(), sector_size());
if (m_disk_cache->read_from_cache(lba + offset, sector_buffer))
continue;
TRY(read_sectors_impl(lba + offset, 1, sector_buffer));
(void)m_disk_cache->write_to_cache(lba + offset, sector_buffer, false);
}
return {};
}
BAN::ErrorOr<void> StorageDevice::write_sectors(uint64_t lba, uint64_t sector_count, const uint8_t* buffer)
BAN::ErrorOr<void> StorageDevice::write_sectors(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
{
// TODO: use disk cache for dirty pages. I don't wanna think about how to do it safely now
ASSERT(buffer.size() >= sector_count * sector_size());
{
LockGuard _(m_lock);
Thread::TerminateBlocker blocker(Thread::current());
if (!m_disk_cache.has_value())
return write_sectors_impl(lba, sector_count, buffer);
}
for (uint8_t offset = 0; offset < sector_count; offset++)
{
LockGuard _(m_lock);
Thread::TerminateBlocker blocker(Thread::current());
const uint8_t* buffer_ptr = buffer + offset * sector_size();
if (!m_disk_cache.has_value() || m_disk_cache->write_to_cache(lba + offset, buffer_ptr, true).is_error())
TRY(write_sectors_impl(lba + offset, 1, buffer_ptr));
auto sector_buffer = buffer.slice(offset * sector_size(), sector_size());
if (m_disk_cache->write_to_cache(lba + offset, sector_buffer, true).is_error())
TRY(write_sectors_impl(lba + offset, 1, sector_buffer));
}
return {};

View File

@ -95,7 +95,7 @@ namespace Kernel
TTY::current()->m_tty_ctrl.semaphore.block();
Input::KeyEvent event;
size_t read = MUST(inode->read(0, &event, sizeof(event)));
size_t read = MUST(inode->read(0, BAN::ByteSpan::from(event)));
ASSERT(read == sizeof(event));
TTY::current()->on_key_event(event);
}
@ -298,7 +298,7 @@ namespace Kernel
putchar_impl(ch);
}
BAN::ErrorOr<size_t> TTY::read_impl(off_t, void* buffer, size_t count)
BAN::ErrorOr<size_t> TTY::read_impl(off_t, BAN::ByteSpan buffer)
{
LockGuard _(m_lock);
while (!m_output.flush)
@ -314,8 +314,8 @@ namespace Kernel
return 0;
}
size_t to_copy = BAN::Math::min<size_t>(count, m_output.bytes);
memcpy(buffer, m_output.buffer.data(), to_copy);
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_output.bytes);
memcpy(buffer.data(), m_output.buffer.data(), to_copy);
memmove(m_output.buffer.data(), m_output.buffer.data() + to_copy, m_output.bytes - to_copy);
m_output.bytes -= to_copy;
@ -328,12 +328,12 @@ namespace Kernel
return to_copy;
}
BAN::ErrorOr<size_t> TTY::write_impl(off_t, const void* buffer, size_t count)
BAN::ErrorOr<size_t> TTY::write_impl(off_t, BAN::ConstByteSpan buffer)
{
LockGuard _(m_lock);
for (size_t i = 0; i < count; i++)
putchar(((uint8_t*)buffer)[i]);
return count;
for (size_t i = 0; i < buffer.size(); i++)
putchar(buffer[i]);
return buffer.size();
}
bool TTY::has_data_impl() const

19
qemu.sh
View File

@ -1,19 +0,0 @@
#!/bin/bash
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 \
-m 128 \
-smp 2 \
$BIOS_ARGS \
-drive format=raw,id=disk,file=${DISK_IMAGE_PATH},if=none \
-device ahci,id=ahci \
-device ide-hd,drive=disk,bus=ahci.0 \
$@ \

View File

@ -14,7 +14,7 @@ COM1_DEVICE=$(cat $COM1_DEVICE_FILE)
rm $COM1_DEVICE_FILE
cat > $BOCHS_CONFIG_FILE << EOF
ata0-master: type=disk, path=$DISK_IMAGE_PATH, status=inserted
ata0-master: type=disk, path=$BANAN_DISK_IMAGE_PATH, status=inserted
boot: disk
clock: sync=realtime, time0=local
display_library: x, options="gui_debug"

107
script/build.sh Executable file
View File

@ -0,0 +1,107 @@
#!/bin/bash
set -e
if [[ -z $BANAN_ARCH ]]; then
export BANAN_ARCH=x86_64
fi
export BANAN_SCRIPT_DIR=$(dirname $(realpath $0))
source $BANAN_SCRIPT_DIR/config.sh
make_build_dir () {
if ! [[ -d $BANAN_BUILD_DIR ]]; then
mkdir -p $BANAN_BUILD_DIR
cd $BANAN_BUILD_DIR
cmake --toolchain=$BANAN_TOOLCHAIN_DIR/Toolchain.txt -G Ninja $BANAN_ROOT_DIR $BANAN_CMAKE_ARGS
fi
}
build_target () {
make_build_dir
if [[ -z $1 ]]; then
echo "No target provided"
exit 1
fi
cd $BANAN_BUILD_DIR
ninja $1
}
build_toolchain () {
$BANAN_TOOLCHAIN_DIR/build.sh
build_target libc-install
$BANAN_TOOLCHAIN_DIR/build.sh libstdc++
}
create_image () {
build_target install-sysroot
if [[ "$1" == "full" ]]; then
$BANAN_SCRIPT_DIR/image-full.sh
else
$BANAN_SCRIPT_DIR/image.sh
fi
}
run_qemu () {
create_image
$BANAN_SCRIPT_DIR/qemu.sh $@
}
run_bochs () {
create_image
$BANAN_SCRIPT_DIR/bochs.sh $@
}
if [[ "$1" == "toolchain" ]]; then
if [[ -f $BANAN_TOOLCHAIN_PREFIX/bin/$BANAN_TOOLCHAIN_TRIPLE_PREFIX-gcc ]]; then
echo "You already seem to have build toolchain."
read -e -p "Do you want to rebuild it [y/N]? " choice
if ! [[ "$choice" == [Yy]* ]]; then
echo "Aborting toolchain rebuild"
exit 0
fi
fi
build_toolchain
exit 0
fi
if [[ "$1" == "image" ]]; then
create_image
exit 0
fi
if [[ "$1" == "image-full" ]]; then
create_image full
exit 0
fi
if [[ "$(uname)" == "Linux" ]]; then
QEMU_ACCEL="-accel kvm"
fi
if [[ "$1" == "qemu" ]]; then
run_qemu -serial stdio $QEMU_ACCEL
exit 0
fi
if [[ "$1" == "qemu-nographic" ]]; then
run_qemu -nographic $QEMU_ACCEL
exit 0
fi
if [[ "$1" == "qemu-debug" ]]; then
run_qemu -serial stdio -d int -no-reboot
exit 0
fi
if [[ "$1" == "bochs" ]]; then
run_bochs
exit 0
fi
if [[ "$1" == "check-fs" ]]; then
$BANAN_SCRIPT_DIR/check-fs.sh
exit 0
fi
build_target $1

14
script/check-fs.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
set -e
if [[ -z $BANAN_DISK_IMAGE_PATH ]]; then
echo "You must set BANAN_DISK_IMAGE_PATH environment variable" >&2
exit 1
fi
LOOP_DEV=$(sudo losetup -f --show $BANAN_DISK_IMAGE_PATH)
sudo partprobe $LOOP_DEV
sudo fsck.ext2 -fn ${LOOP_DEV}p2 || true
sudo losetup -d $LOOP_DEV

27
script/config.sh Normal file
View File

@ -0,0 +1,27 @@
if [[ -z $BANAN_ROOT_DIR ]]; then
if [[ -z $BANAN_SCRIPT_DIR ]]; then
export BANAN_ROOT_DIR=$BANAN_SCRIPT_DIR/..
else
echo "You must set the BANAN_ROOT_DIR environment variable" >&2
exit 1
fi
fi
if [[ -z $BANAN_ARCH ]]; then
echo "You must set the BANAN_ARCH environment variable" >&2
exit 1
fi
export BANAN_TOOLCHAIN_DIR=$BANAN_ROOT_DIR/toolchain
export BANAN_TOOLCHAIN_PREFIX=$BANAN_TOOLCHAIN_DIR/local
export BANAN_TOOLCHAIN_TRIPLE_PREFIX=$BANAN_ARCH-banan_os
export BANAN_BUILD_DIR=$BANAN_ROOT_DIR/build
export BANAN_SYSROOT=$BANAN_BUILD_DIR/sysroot
export BANAN_DISK_IMAGE_PATH=$BANAN_BUILD_DIR/banan-os.img
if [[ -z $BANAN_UEFI_BOOT ]]; then
export BANAN_UEFI_BOOT=0
fi

View File

@ -1,14 +1,34 @@
#!/bin/bash
set -e
if [[ -z $BANAN_DISK_IMAGE_PATH ]]; then
echo "You must set the BANAN_DISK_IMAGE_PATH environment variable" >&2
exit 1
fi
if [[ -z $BANAN_SYSROOT ]]; then
echo "You must set the BANAN_SYSROOT environment variable" >&2
exit 1
fi
if [[ -z $BANAN_TOOLCHAIN_PREFIX ]]; then
echo "You must set the BANAN_TOOLCHAIN_PREFIX environment variable" >&2
exit 1
fi
if [[ -z $BANAN_ARCH ]]; then
echo "You must set the BANAN_ARCH environment variable" >&2
exit 1
fi
DISK_SIZE=$[50 * 1024 * 1024]
MOUNT_DIR=/mnt
truncate -s 0 "$DISK_IMAGE_PATH"
truncate -s $DISK_SIZE "$DISK_IMAGE_PATH"
truncate -s 0 "$BANAN_DISK_IMAGE_PATH"
truncate -s $DISK_SIZE "$BANAN_DISK_IMAGE_PATH"
if [ "$UEFI_BOOT" == "1" ]; then
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk "$DISK_IMAGE_PATH" > /dev/null
if [ "$BANAN_UEFI_BOOT" == "1" ]; then
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk "$BANAN_DISK_IMAGE_PATH" > /dev/null
g # gpt
n # new partition
1 # partition number 1
@ -27,7 +47,7 @@ if [ "$UEFI_BOOT" == "1" ]; then
w # write changes
EOF
else
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk "$DISK_IMAGE_PATH" > /dev/null
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk "$BANAN_DISK_IMAGE_PATH" > /dev/null
g # gpt
n # new partition
1 # partition number 1
@ -47,30 +67,30 @@ else
EOF
fi
LOOP_DEV=$(sudo losetup -f --show "$DISK_IMAGE_PATH")
LOOP_DEV=$(sudo losetup -f --show "$BANAN_DISK_IMAGE_PATH")
sudo partprobe $LOOP_DEV
PARTITION1=${LOOP_DEV}p1
PARTITION2=${LOOP_DEV}p2
sudo mkfs.ext2 -d $SYSROOT -b 1024 -q $PARTITION2
sudo mkfs.ext2 -d $BANAN_SYSROOT -b 1024 -q $PARTITION2
if [[ "$UEFI_BOOT" == "1" ]]; then
if [[ "$BANAN_UEFI_BOOT" == "1" ]]; then
sudo mkfs.fat $PARTITION1 > /dev/null
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 "$BANAN_TOOLCHAIN_PREFIX/bin/grub-mkstandalone" -O "$BANAN_ARCH-efi" -o "$MOUNT_DIR/EFI/BOOT/BOOTX64.EFI" "boot/grub/grub.cfg=$BANAN_TOOLCHAIN_PREFIX/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 cp "$BANAN_TOOLCHAIN_PREFIX/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 cp "$BANAN_TOOLCHAIN_PREFIX/grub-legacy-boot.cfg" "$MOUNT_DIR/boot/grub/grub.cfg"
sudo umount "$MOUNT_DIR"
fi

45
script/image.sh Executable file
View File

@ -0,0 +1,45 @@
#!/bin/bash
if [[ -z $BANAN_ROOT_DIR ]]; then
echo "You must set the BANAN_ROOT_DIR environment variable" >&2
exit 1
fi
if [[ -z $BANAN_DISK_IMAGE_PATH ]]; then
echo "You must set the BANAN_DISK_IMAGE_PATH environment variable" >&2
exit 1
fi
if [[ -z $BANAN_SYSROOT ]]; then
echo "You must set the BANAN_SYSROOT environment variable" >&2
exit 1
fi
if [[ ! -f $BANAN_DISK_IMAGE_PATH ]]; then
$BANAN_SCRIPT_DIR/image-full.sh
exit 0
fi
fdisk -l $BANAN_DISK_IMAGE_PATH | grep -q 'EFI System'; IMAGE_IS_UEFI=$?
[[ $BANAN_UEFI_BOOT == 1 ]]; CREATE_IS_UEFI=$?
if [[ $IMAGE_IS_UEFI -ne $CREATE_IS_UEFI ]]; then
echo Converting disk image to/from UEFI
$BANAN_SCRIPT_DIR/image-full.sh
exit 0
fi
MOUNT_DIR=/mnt
LOOP_DEV=$(sudo losetup -f --show $BANAN_DISK_IMAGE_PATH)
sudo partprobe $LOOP_DEV
ROOT_PARTITON=${LOOP_DEV}p2
sudo mount $ROOT_PARTITON $MOUNT_DIR
sudo rsync -a ${BANAN_SYSROOT}/* ${MOUNT_DIR}/
sudo umount $MOUNT_DIR
sudo losetup -d $LOOP_DEV

24
script/qemu.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
set -e
if [[ -z $BANAN_DISK_IMAGE_PATH ]]; then
echo "You must set the BANAN_DISK_IMAGE_PATH environment variable" >&2
exit 1
fi
if [[ -z $OVMF_PATH ]]; then
OVMF_PATH="/usr/share/ovmf/x64/OVMF.fd"
fi
if [[ "$BANAN_UEFI_BOOT" == "1" ]]; then
BIOS_ARGS="-bios $OVMF_PATH -net none"
fi
qemu-system-$BANAN_ARCH \
-m 128 \
-smp 2 \
$BIOS_ARGS \
-drive format=raw,id=disk,file=${BANAN_DISK_IMAGE_PATH},if=none \
-device ahci,id=ahci \
-device ide-hd,drive=disk,bus=ahci.0 \
$@ \

18
toolchain/Toolchain.txt Normal file
View File

@ -0,0 +1,18 @@
if (NOT DEFINED ENV{BANAN_ARCH})
message(FATAL_ERROR "environment variable BANAN_ARCH not defined")
endif ()
set(BANAN_ARCH $ENV{BANAN_ARCH})
set(TOOLCHAIN_PREFIX ${CMAKE_SOURCE_DIR}/toolchain/local)
set(CMAKE_SYSTEM_NAME banan-os)
set(CMAKE_SYSTEM_PROCESSOR AMD64)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}/bin/${BANAN_ARCH}-banan_os-g++)
set(CMAKE_CXX_COMPILER_WORKS True)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}/bin/${BANAN_ARCH}-banan_os-gcc)
set(CMAKE_C_COMPILER_WORKS True)

View File

@ -5,36 +5,36 @@ BINUTILS_VERSION="binutils-2.39"
GCC_VERSION="gcc-12.2.0"
GRUB_VERSION="grub-2.06"
cd $(dirname "$0")
if [[ -n $LIBSTDCPP ]]; then
cd build/${GCC_VERSION}/
make -j $(nproc) all-target-libstdc++-v3
make install-target-libstdc++-v3
exit 0
fi
if [[ -z $SYSROOT ]]; then
echo "You must set the SYSROOT environment variable" >&2
if [[ -z $BANAN_SYSROOT ]]; then
echo "You must set the BANAN_SYSROOT environment variable" >&2
exit 1
fi
if [[ -z $PREFIX ]]; then
echo "You must set the PREFIX environment variable" >&2
if [[ -z $BANAN_TOOLCHAIN_DIR ]]; then
echo "You must set the BANAN_TOOLCHAIN_DIR environment variable" >&2
exit 1
fi
if [[ -z $ARCH ]]; then
echo "You must set the ARCH environment variable" >&2
if [[ -z $BANAN_TOOLCHAIN_PREFIX ]]; then
echo "You must set the BANAN_TOOLCHAIN_PREFIX environment variable" >&2
exit 1
fi
TARGET="${ARCH}-banan_os"
if [[ -z $BANAN_TOOLCHAIN_TRIPLE_PREFIX ]]; then
echo "You must set the BANAN_TOOLCHAIN_TRIPLE_PREFIX environment variable" >&2
exit 1
fi
if [ ! -f ${PREFIX}/bin/${TARGET}-ld ]; then
if [[ -z $BANAN_ARCH ]]; then
echo "You must set the BANAN_ARCH environment variable" >&2
exit 1
fi
build_binutils () {
echo "Building ${BINUTILS_VERSION}"
cd $BANAN_TOOLCHAIN_DIR
if [ ! -f ${BINUTILS_VERSION}.tar.xz ]; then
wget https://ftp.gnu.org/gnu/binutils/${BINUTILS_VERSION}.tar.xz
fi
@ -45,26 +45,24 @@ if [ ! -f ${PREFIX}/bin/${TARGET}-ld ]; then
fi
mkdir -p build/${BINUTILS_VERSION}/
pushd build/${BINUTILS_VERSION}/
cd build/${BINUTILS_VERSION}/
../../${BINUTILS_VERSION}/configure \
--target="$TARGET" \
--prefix="$PREFIX" \
--with-sysroot="$SYSROOT" \
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
--with-sysroot="$BANAN_SYSROOT" \
--disable-nls \
--disable-werror
make -j $(nproc)
make install
}
popd
fi
if [ ! -f ${PREFIX}/bin/${TARGET}-g++ ]; then
build_gcc () {
echo "Building ${GCC_VERSION}"
cd $BANAN_TOOLCHAIN_DIR
if [ ! -f ${GCC_VERSION}.tar.xz ]; then
wget https://ftp.gnu.org/gnu/gcc/${GCC_VERSION}/${GCC_VERSION}.tar.xz
fi
@ -75,27 +73,25 @@ if [ ! -f ${PREFIX}/bin/${TARGET}-g++ ]; then
fi
mkdir -p build/${GCC_VERSION}/
pushd build/${GCC_VERSION}/
cd build/${GCC_VERSION}/
../../${GCC_VERSION}/configure \
--target="$TARGET" \
--prefix="$PREFIX" \
--with-sysroot="$SYSROOT" \
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
--with-sysroot="$BANAN_SYSROOT" \
--disable-nls \
--enable-languages=c,c++
make -j $(nproc) all-gcc
make -j $(nproc) all-target-libgcc CFLAGS_FOR_TARGET='-g -O2 -mcmodel=large -mno-red-zone'
make install-gcc install-target-libgcc
}
popd
fi
if [ ! -f ${PREFIX}/bin/grub-mkstandalone ]; then
build_grub () {
echo "Building ${GRUB_VERSION}"
cd $BANAN_TOOLCHAIN_DIR
if [ ! -f ${GRUB_VERSION}.tar.xz ]; then
wget https://ftp.gnu.org/gnu/grub/${GRUB_VERSION}.tar.xz
fi
@ -105,17 +101,29 @@ if [ ! -f ${PREFIX}/bin/grub-mkstandalone ]; then
fi
mkdir -p build/${GRUB_VERSION}/
pushd build/${GRUB_VERSION}/
cd build/${GRUB_VERSION}/
../../${GRUB_VERSION}/configure \
--target="$ARCH" \
--prefix="$PREFIX" \
--target="$BANAN_ARCH" \
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
--with-platform="efi" \
--disable-werror
make -j $(nproc)
make install
}
popd
build_libstdcpp () {
cd build/${GCC_VERSION}/
make -j $(nproc) all-target-libstdc++-v3
make install-target-libstdc++-v3
}
if [[ "$1" == "libstdc++" ]]; then
build_libstdcpp
exit 0
fi
build_binutils
build_gcc
build_grub

1
toolchain/local/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*/