Compare commits

..

No commits in common. "00ee86920a73ca91333f84e58a74b30529eb9905" and "e2e5c31d54d398e55944269f4d684961f8d48835" have entirely different histories.

54 changed files with 405 additions and 699 deletions

View File

@ -1,121 +0,0 @@
#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,8 +43,6 @@ 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,13 +1,35 @@
cmake_minimum_required(VERSION 3.26)
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "banan-os")
message(FATAL_ERROR "CMAKE_SYSTEM_NAME is not banan-os")
endif ()
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()
add_compile_options(-mno-sse -mno-sse2)
add_compile_definitions(__enable_sse=0)
project(banan-os CXX C ASM)
project(banan-os CXX)
set(BANAN_BASE_SYSROOT ${CMAKE_SOURCE_DIR}/base-sysroot.tar.gz)
set(BANAN_SYSROOT ${CMAKE_BINARY_DIR}/sysroot)
@ -15,6 +37,7 @@ 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)
@ -35,10 +58,63 @@ add_custom_target(headers
DEPENDS libelf-headers
)
add_custom_target(install-sysroot
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
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, BAN::ByteSpan::from(m_file_header)));
size_t nread = TRY(m_inode->read(0, &m_file_header, sizeof(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, BAN::ByteSpan::from(m_program_headers[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));
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, { (uint8_t*)vaddr + vaddr_offset, bytes }));
TRY(m_inode->read(program_header.p_offset + file_offset, (void*)(vaddr + vaddr_offset), bytes));
}
return {};

1
PreLoad.cmake Normal file
View File

@ -0,0 +1 @@
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, ATA AHCI drivers, 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, 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,32 +14,41 @@ 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
./script/build.sh toolchain
ninja toolchain
cmake --fresh .. # We need to reconfigure cmake to use the new compiler
ninja libstdc++
```
To build the os itself you can run one of the following commands. You will need root access since the sysroot has "proper" permissions.
To build the os itself you can run either of the following commands. You will need root access since the sysroot has "proper" permissions.
```sh
./script/build.sh qemu
./script/build.sh qemu-nographic
./script/build.sh qemu-debug
./script/build.sh bochs
ninja qemu
ninja bochs
```
You can also build the kernel or disk image without running it:
```sh
./script/build.sh kernel
./script/build.sh image
ninja kernel
ninja image
```
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.
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.
```sh
./script/build.sh image-full
ninja image-full
```
> ***NOTE*** ```ninja clean``` has to be ran with root permissions, since it deletes from the banan-so sysroot.
> ***NOTE*** ```ninja clean``` has to be ran with root permissions, since it deletes the root filesystem.
### Contributing

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=$BANAN_DISK_IMAGE_PATH, status=inserted
ata0-master: type=disk, path=$DISK_IMAGE_PATH, status=inserted
boot: disk
clock: sync=realtime, time0=local
display_library: x, options="gui_debug"

10
check-fs.sh Executable file
View File

@ -0,0 +1,10 @@
#!/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,34 +1,14 @@
#!/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 "$BANAN_DISK_IMAGE_PATH"
truncate -s $DISK_SIZE "$BANAN_DISK_IMAGE_PATH"
truncate -s 0 "$DISK_IMAGE_PATH"
truncate -s $DISK_SIZE "$DISK_IMAGE_PATH"
if [ "$BANAN_UEFI_BOOT" == "1" ]; then
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk "$BANAN_DISK_IMAGE_PATH" > /dev/null
if [ "$UEFI_BOOT" == "1" ]; then
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk "$DISK_IMAGE_PATH" > /dev/null
g # gpt
n # new partition
1 # partition number 1
@ -47,7 +27,7 @@ if [ "$BANAN_UEFI_BOOT" == "1" ]; then
w # write changes
EOF
else
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk "$BANAN_DISK_IMAGE_PATH" > /dev/null
sed -e 's/\s*\([-\+[:alnum:]]*\).*/\1/' << EOF | fdisk "$DISK_IMAGE_PATH" > /dev/null
g # gpt
n # new partition
1 # partition number 1
@ -67,30 +47,30 @@ else
EOF
fi
LOOP_DEV=$(sudo losetup -f --show "$BANAN_DISK_IMAGE_PATH")
LOOP_DEV=$(sudo losetup -f --show "$DISK_IMAGE_PATH")
sudo partprobe $LOOP_DEV
PARTITION1=${LOOP_DEV}p1
PARTITION2=${LOOP_DEV}p2
sudo mkfs.ext2 -d $BANAN_SYSROOT -b 1024 -q $PARTITION2
sudo mkfs.ext2 -d $SYSROOT -b 1024 -q $PARTITION2
if [[ "$BANAN_UEFI_BOOT" == "1" ]]; then
if [[ "$UEFI_BOOT" == "1" ]]; then
sudo mkfs.fat $PARTITION1 > /dev/null
sudo mount $PARTITION1 "$MOUNT_DIR"
sudo mkdir -p "$MOUNT_DIR/EFI/BOOT"
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 "$TOOLCHAIN/bin/grub-mkstandalone" -O "$BANAN_ARCH-efi" -o "$MOUNT_DIR/EFI/BOOT/BOOTX64.EFI" "boot/grub/grub.cfg=$TOOLCHAIN/grub-memdisk.cfg"
sudo umount "$MOUNT_DIR"
sudo mount $PARTITION2 "$MOUNT_DIR"
sudo mkdir -p "$MOUNT_DIR/boot/grub"
sudo cp "$BANAN_TOOLCHAIN_PREFIX/grub-uefi.cfg" "$MOUNT_DIR/boot/grub/grub.cfg"
sudo cp "$TOOLCHAIN/grub-uefi.cfg" "$MOUNT_DIR/boot/grub/grub.cfg"
sudo umount "$MOUNT_DIR"
else
sudo mount $PARTITION2 "$MOUNT_DIR"
sudo grub-install --no-floppy --target=i386-pc --modules="normal ext2 multiboot" --boot-directory="$MOUNT_DIR/boot" $LOOP_DEV
sudo mkdir -p "$MOUNT_DIR/boot/grub"
sudo cp "$BANAN_TOOLCHAIN_PREFIX/grub-legacy-boot.cfg" "$MOUNT_DIR/boot/grub/grub.cfg"
sudo cp "$TOOLCHAIN/grub-legacy-boot.cfg" "$MOUNT_DIR/boot/grub/grub.cfg"
sudo umount "$MOUNT_DIR"
fi

30
image.sh Executable file
View File

@ -0,0 +1,30 @@
#!/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, BAN::ByteSpan) override { return 0; }
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return buffer.size(); };
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; };
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, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return buffer.size(); };
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; };
private:
const dev_t m_rdev;

View File

@ -33,9 +33,6 @@ 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, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) 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<void> truncate_impl(size_t) override;
private:

View File

@ -1,11 +1,10 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/RefPtr.h>
#include <BAN/String.h>
#include <BAN/StringView.h>
#include <BAN/Vector.h>
#include <BAN/WeakPtr.h>
#include <BAN/Vector.h>
#include <kernel/API/DirectoryEntry.h>
#include <kernel/Credentials.h>
@ -96,8 +95,8 @@ namespace Kernel
BAN::ErrorOr<BAN::String> link_target();
// General API
BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer);
BAN::ErrorOr<size_t> write(off_t, BAN::ConstByteSpan buffer);
BAN::ErrorOr<size_t> read(off_t, void*, size_t);
BAN::ErrorOr<size_t> write(off_t, const void*, size_t);
BAN::ErrorOr<void> truncate(size_t);
bool has_data() const;
@ -112,8 +111,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, 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<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<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, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) 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;
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, BAN::ByteSpan) const, RamFileSystem&, mode_t, uid_t, gid_t);
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);
~ProcROInode() = default;
protected:
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
// You may not write here and this is always non blocking
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(EINVAL); }
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) 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, BAN::ByteSpan) const, RamFileSystem&, const FullInodeInfo&);
ProcROInode(Process&, size_t (Process::*)(off_t, void*, size_t) const, RamFileSystem&, const FullInodeInfo&);
private:
Process& m_process;
size_t (Process::*m_callback)(off_t, BAN::ByteSpan) const;
size_t (Process::*m_callback)(off_t, void*, size_t) const;
};
}

View File

@ -70,8 +70,8 @@ namespace Kernel
protected:
RamFileInode(RamFileSystem&, const FullInodeInfo&);
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<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<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, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) 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, BAN::ByteSpan);
BAN::ErrorOr<size_t> write(int fd, BAN::ConstByteSpan);
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<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, BAN::ByteSpan) const;
size_t proc_cmdline(off_t offset, BAN::ByteSpan) const;
size_t proc_environ(off_t offset, BAN::ByteSpan) const;
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;
bool is_userspace() const { return m_is_userspace; }
const userspace_info_t& userspace_info() const { return m_userspace_info; }

View File

@ -23,15 +23,14 @@ 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, BAN::ByteSpan) override;
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan) override;
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;
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();
BAN::ErrorOr<void> block_until_command_completed(uint32_t command_slot);
void block_until_irq();
private:
BAN::RefPtr<AHCIController> m_controller;
@ -42,6 +41,8 @@ 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,6 +1,5 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/RefPtr.h>
#include <BAN/Vector.h>
#include <kernel/InterruptController.h>
@ -23,8 +22,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 lba, uint64_t sector_count, BAN::ByteSpan);
BAN::ErrorOr<void> write(ATADevice&, uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan);
BAN::ErrorOr<void> read(ATADevice&, uint64_t, uint8_t, uint8_t*);
BAN::ErrorOr<void> write(ATADevice&, uint64_t, uint8_t, const uint8_t*);
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, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) 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;
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, BAN::ByteSpan) override;
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t, uint64_t, BAN::ConstByteSpan) override;
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;
private:
BAN::RefPtr<ATABus> m_bus;

View File

@ -1,7 +1,6 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/ByteSpan.h>
#include <kernel/Memory/Types.h>
#include <kernel/SpinLock.h>
@ -16,8 +15,8 @@ namespace Kernel
DiskCache(size_t sector_size, StorageDevice&);
~DiskCache();
bool read_from_cache(uint64_t sector, BAN::ByteSpan);
BAN::ErrorOr<void> write_to_cache(uint64_t sector, BAN::ConstByteSpan, bool dirty);
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);
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, BAN::ByteSpan);
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint8_t sector_count, BAN::ConstByteSpan);
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);
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, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) 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, BAN::ByteSpan);
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan);
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);
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, BAN::ByteSpan) = 0;
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan) = 0;
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;
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, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) 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;
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, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> ZeroDevice::read_impl(off_t, void* buffer, size_t bytes)
{
memset(buffer.data(), 0, buffer.size());
return buffer.size();
memset(buffer, 0, bytes);
return bytes;
}
}

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.span()));
TRY(m_partition.read_sectors(lba, sector_count, superblock_buffer.data()));
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.span()));
MUST(m_partition.read_sectors(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.data()));
}
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.span()));
MUST(m_partition.write_sectors(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.data()));
}
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.span()));
MUST(m_partition.read_sectors(lba, sector_count, superblock_buffer.data()));
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.span()));
MUST(m_partition.write_sectors(lba, sector_count, superblock_buffer.data()));
}
}

View File

@ -100,21 +100,19 @@ namespace Kernel
return BAN::Error::from_errno(ENOTSUP);
}
BAN::ErrorOr<size_t> Ext2Inode::read_impl(off_t offset, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> Ext2Inode::read_impl(off_t offset, void* buffer, size_t count)
{
// FIXME: update atime if needed
ASSERT(!mode().ifdir());
ASSERT(offset >= 0);
if (offset >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
if (offset >= UINT32_MAX || count >= UINT32_MAX || offset + count >= UINT32_MAX)
return BAN::Error::from_errno(EOVERFLOW);
if (offset >= m_inode.size)
return 0;
uint32_t count = buffer.size();
if (offset + buffer.size() > m_inode.size)
if (offset + count > m_inode.size)
count = m_inode.size - offset;
const uint32_t block_size = blksize();
@ -133,7 +131,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(buffer.data() + n_read, block_buffer.data() + copy_offset, to_copy);
memcpy((uint8_t*)buffer + n_read, block_buffer.data() + copy_offset, to_copy);
n_read += to_copy;
}
@ -141,25 +139,26 @@ namespace Kernel
return n_read;
}
BAN::ErrorOr<size_t> Ext2Inode::write_impl(off_t offset, BAN::ConstByteSpan buffer)
BAN::ErrorOr<size_t> Ext2Inode::write_impl(off_t offset, const void* buffer, size_t count)
{
// FIXME: update atime if needed
ASSERT(!mode().ifdir());
ASSERT(offset >= 0);
if (offset >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
if (offset >= UINT32_MAX || count >= UINT32_MAX || offset + count >= UINT32_MAX)
return BAN::Error::from_errno(EOVERFLOW);
if (m_inode.size < offset + buffer.size())
TRY(truncate_impl(offset + buffer.size()));
if (m_inode.size < offset + count)
TRY(truncate_impl(offset + count));
const uint32_t block_size = blksize();
auto block_buffer = m_fs.get_block_buffer();
size_t written = 0;
size_t to_write = buffer.size();
const uint8_t* u8buffer = (const uint8_t*)buffer;
size_t to_write = count;
// Write partial block
if (offset % block_size)
@ -170,10 +169,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, buffer.data(), to_copy);
memcpy(block_buffer.data() + block_offset, u8buffer, to_copy);
m_fs.write_block(block_index, block_buffer);
written += to_copy;
u8buffer += to_copy;
offset += to_copy;
to_write -= to_copy;
}
@ -182,10 +181,10 @@ namespace Kernel
{
uint32_t block_index = fs_block_of_data_block_index(offset / block_size);
memcpy(block_buffer.data(), buffer.data() + written, block_buffer.size());
memcpy(block_buffer.data(), u8buffer, block_buffer.size());
m_fs.write_block(block_index, block_buffer);
written += block_size;
u8buffer += block_size;
offset += block_size;
to_write -= block_size;
}
@ -195,11 +194,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(), buffer.data() + written, to_write);
memcpy(block_buffer.data(), u8buffer, to_write);
m_fs.write_block(block_index, block_buffer);
}
return buffer.size();
return count;
}
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, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> Inode::read(off_t offset, void* buffer, size_t bytes)
{
LockGuard _(m_lock);
Thread::TerminateBlocker blocker(Thread::current());
if (mode().ifdir())
return BAN::Error::from_errno(EISDIR);
return read_impl(offset, buffer);
return read_impl(offset, buffer, bytes);
}
BAN::ErrorOr<size_t> Inode::write(off_t offset, BAN::ConstByteSpan buffer)
BAN::ErrorOr<size_t> Inode::write(off_t offset, const void* buffer, size_t bytes)
{
LockGuard _(m_lock);
Thread::TerminateBlocker blocker(Thread::current());
if (mode().ifdir())
return BAN::Error::from_errno(EISDIR);
return write_impl(offset, buffer);
return write_impl(offset, buffer, bytes);
}
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, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, void* buffer, size_t count)
{
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>(buffer.size(), m_buffer.size());
memcpy(buffer.data(), m_buffer.data(), to_copy);
size_t to_copy = BAN::Math::min<size_t>(count, m_buffer.size());
memcpy(buffer, 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, BAN::ConstByteSpan buffer)
BAN::ErrorOr<size_t> Pipe::write_impl(off_t, const void* buffer, size_t count)
{
LockGuard _(m_lock);
size_t old_size = m_buffer.size();
TRY(m_buffer.resize(old_size + buffer.size()));
memcpy(m_buffer.data() + old_size, buffer.data(), buffer.size());
TRY(m_buffer.resize(old_size + count));
memcpy(m_buffer.data() + old_size, buffer, count);
timespec current_time = SystemTimer::get().real_time();
m_mtime = current_time;
@ -79,7 +79,7 @@ namespace Kernel
m_semaphore.unblock();
return buffer.size();
return count;
}
}

View File

@ -25,7 +25,7 @@ namespace Kernel
{
}
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)
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)
{
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, BAN::ByteSpan) const, RamFileSystem& fs, const FullInodeInfo& inode_info)
ProcROInode::ProcROInode(Process& process, size_t (Process::*callback)(off_t, void*, size_t) 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, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> ProcROInode::read_impl(off_t offset, void* buffer, size_t buffer_size)
{
ASSERT(offset >= 0);
if ((size_t)offset >= sizeof(proc_meminfo_t))
return 0;
return (m_process.*m_callback)(offset, buffer);
return (m_process.*m_callback)(offset, buffer, buffer_size);
}
}

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, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> RamFileInode::read_impl(off_t offset, void* buffer, size_t bytes)
{
ASSERT(offset >= 0);
if (offset >= size())
return 0;
size_t to_copy = BAN::Math::min<size_t>(m_inode_info.size - offset, buffer.size());
memcpy(buffer.data(), m_data.data(), to_copy);
size_t to_copy = BAN::Math::min<size_t>(m_inode_info.size - offset, bytes);
memcpy(buffer, m_data.data(), to_copy);
return to_copy;
}
BAN::ErrorOr<size_t> RamFileInode::write_impl(off_t offset, BAN::ConstByteSpan buffer)
BAN::ErrorOr<size_t> RamFileInode::write_impl(off_t offset, const void* buffer, size_t bytes)
{
ASSERT(offset >= 0);
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();
if (offset + bytes > (size_t)size())
TRY(truncate_impl(offset + bytes));
memcpy(m_data.data() + offset, buffer, bytes);
return bytes;
}
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.span()));
TRY(inode->read(0, file_data.data(), file_data.size()));
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, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> PS2Keyboard::read_impl(off_t, void* buffer, size_t size)
{
if (buffer.size() < sizeof(KeyEvent))
if (size < sizeof(KeyEvent))
return BAN::Error::from_errno(ENOBUFS);
while (true)
@ -231,7 +231,7 @@ namespace Kernel::Input
if (m_event_queue.empty())
continue;
buffer.as<KeyEvent>() = m_event_queue.front();
*(KeyEvent*)buffer = 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, BAN::ConstByteSpan::from(page_buffer)); ret.is_error())
if (auto ret = inode->write(i * PAGE_SIZE, page_buffer, PAGE_SIZE); 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, BAN::ByteSpan((uint8_t*)vaddr, bytes));
read_ret = m_inode->read(file_offset, (void*)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, BAN::ByteSpan((uint8_t*)0, bytes));
read_ret = m_inode->read(file_offset, (void*)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, BAN::ByteSpan(m_shared_data->page_buffer, bytes)));
TRY(m_inode->read(offset, 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, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> OpenFileDescriptorSet::read(int fd, void* buffer, size_t count)
{
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));
size_t nread = TRY(open_file->inode->read(open_file->offset, buffer, count));
open_file->offset += nread;
return nread;
}
BAN::ErrorOr<size_t> OpenFileDescriptorSet::write(int fd, BAN::ConstByteSpan buffer)
BAN::ErrorOr<size_t> OpenFileDescriptorSet::write(int fd, const void* buffer, size_t count)
{
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));
size_t nwrite = TRY(open_file->inode->write(open_file->offset, buffer, count));
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, BAN::ByteSpan buffer) const
size_t Process::proc_meminfo(off_t offset, void* buffer, size_t buffer_size) 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.data(), (uint8_t*)&meminfo + offset, bytes);
size_t bytes = BAN::Math::min<size_t>(sizeof(proc_meminfo_t) - offset, buffer_size);
memcpy(buffer, (uint8_t*)&meminfo + offset, bytes);
return bytes;
}
static size_t read_from_vec_of_str(const BAN::Vector<BAN::String>& container, size_t start, BAN::ByteSpan buffer)
static size_t read_from_vec_of_str(const BAN::Vector<BAN::String>& container, size_t start, void* buffer, size_t buffer_size)
{
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(buffer.data() + written, elem.data() + elem_offset, bytes);
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);
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, BAN::ByteSpan buffer) const
size_t Process::proc_cmdline(off_t offset, void* buffer, size_t buffer_size) const
{
LockGuard _(m_lock);
return read_from_vec_of_str(m_cmdline, offset, buffer);
return read_from_vec_of_str(m_cmdline, offset, buffer, buffer_size);
}
size_t Process::proc_environ(off_t offset, BAN::ByteSpan buffer) const
size_t Process::proc_environ(off_t offset, void* buffer, size_t buffer_size) const
{
LockGuard _(m_lock);
return read_from_vec_of_str(m_environ, offset, buffer);
return read_from_vec_of_str(m_environ, offset, buffer, buffer_size);
}
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, BAN::ByteSpan((uint8_t*)buffer, count)));
return TRY(m_open_file_descriptors.read(fd, 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, BAN::ByteSpan((uint8_t*)buffer, count)));
return TRY(m_open_file_descriptors.write(fd, buffer, count));
}
BAN::ErrorOr<long> Process::sys_pipe(int fildes[2])

View File

@ -1,4 +1,3 @@
#include <kernel/Scheduler.h>
#include <kernel/Storage/ATA/AHCI/Controller.h>
#include <kernel/Storage/ATA/AHCI/Device.h>
#include <kernel/Storage/ATA/ATADefinitions.h>
@ -41,7 +40,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() / sizeof(uint16_t) }));
TRY(detail::ATABaseDevice::initialize({ (const uint16_t*)m_data_dma_region->vaddr(), m_data_dma_region->size() }));
return {};
}
@ -121,7 +120,8 @@ namespace Kernel
m_port->ci = 1 << slot.value();
TRY(block_until_command_completed(slot.value()));
// FIXME: timeout
do { block_until_irq(); } while (m_port->ci & (1 << slot.value()));
return {};
}
@ -145,58 +145,41 @@ 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;
}
BAN::ErrorOr<void> AHCIDevice::block_until_command_completed(uint32_t command_slot)
void AHCIDevice::block_until_irq()
{
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);
while (!__sync_bool_compare_and_swap(&m_has_got_irq, true, false))
__builtin_ia32_pause();
}
BAN::ErrorOr<void> AHCIDevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
BAN::ErrorOr<void> AHCIDevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, uint8_t* 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.data() + sector_off * sector_size(), (void*)m_data_dma_region->vaddr(), to_read * sector_size());
memcpy(buffer + 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, BAN::ConstByteSpan buffer)
BAN::ErrorOr<void> AHCIDevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, const uint8_t* 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.data() + sector_off * sector_size(), to_read * sector_size());
memcpy((void*)m_data_dma_region->vaddr(), buffer + sector_off * sector_size(), to_read * sector_size());
TRY(send_command_and_block(lba + sector_off, to_read, Command::Write));
}
@ -275,7 +258,8 @@ namespace Kernel
m_port->ci = 1 << slot.value();
TRY(block_until_command_completed(slot.value()));
// FIXME: timeout
do { block_until_irq(); } while (m_port->ci & (1 << slot.value()));
return {};
}

View File

@ -228,10 +228,8 @@ namespace Kernel
return BAN::Error::from_error_code(ErrorCode::None);
}
BAN::ErrorOr<void> ATABus::read(ATADevice& device, uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
BAN::ErrorOr<void> ATABus::read(ATADevice& device, uint64_t lba, uint8_t sector_count, uint8_t* 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);
@ -253,7 +251,7 @@ namespace Kernel
for (uint32_t sector = 0; sector < sector_count; sector++)
{
block_until_irq();
read_buffer(ATA_PORT_DATA, (uint16_t*)buffer.data() + sector * device.words_per_sector(), device.words_per_sector());
read_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device.words_per_sector(), device.words_per_sector());
}
}
else
@ -265,10 +263,8 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> ATABus::write(ATADevice& device, uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
BAN::ErrorOr<void> ATABus::write(ATADevice& device, uint64_t lba, uint8_t sector_count, const uint8_t* 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);
@ -289,7 +285,7 @@ namespace Kernel
for (uint32_t sector = 0; sector < sector_count; sector++)
{
write_buffer(ATA_PORT_DATA, (uint16_t*)buffer.data() + sector * device.words_per_sector(), device.words_per_sector());
write_buffer(ATA_PORT_DATA, (uint16_t*)buffer + 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, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> detail::ATABaseDevice::read_impl(off_t offset, void* buffer, size_t bytes)
{
if (offset % sector_size())
return BAN::Error::from_errno(EINVAL);
if (buffer.size() % sector_size())
if (bytes % sector_size())
return BAN::Error::from_errno(EINVAL);
TRY(read_sectors(offset / sector_size(), buffer.size() / sector_size(), buffer));
return buffer.size();
TRY(read_sectors(offset / sector_size(), bytes / sector_size(), (uint8_t*)buffer));
return bytes;
}
BAN::ErrorOr<size_t> detail::ATABaseDevice::write_impl(off_t offset, BAN::ConstByteSpan buffer)
BAN::ErrorOr<size_t> detail::ATABaseDevice::write_impl(off_t offset, const void* buffer, size_t bytes)
{
if (offset % sector_size())
return BAN::Error::from_errno(EINVAL);
if (buffer.size() % sector_size())
if (bytes % sector_size())
return BAN::Error::from_errno(EINVAL);
TRY(write_sectors(offset / sector_size(), buffer.size() / sector_size(), buffer));
return buffer.size();
TRY(write_sectors(offset / sector_size(), bytes / sector_size(), (const uint8_t*)buffer));
return bytes;
}
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,16 +118,14 @@ namespace Kernel
, m_is_secondary(is_secondary)
{ }
BAN::ErrorOr<void> ATADevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
BAN::ErrorOr<void> ATADevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, uint8_t* 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, BAN::ConstByteSpan buffer)
BAN::ErrorOr<void> ATADevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, const uint8_t* buffer)
{
ASSERT(buffer.size() >= sector_count * sector_size());
TRY(m_bus->write(*this, lba, sector_count, buffer));
return {};
}

View File

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

View File

@ -153,10 +153,8 @@ namespace Kernel
if (total_size() < sizeof(GPTHeader))
return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader);
BAN::Vector<uint8_t> lba1;
TRY(lba1.resize(sector_size()));
TRY(read_sectors(1, 1, lba1.span()));
BAN::Vector<uint8_t> lba1(sector_size());
TRY(read_sectors(1, 1, lba1.data()));
const GPTHeader& header = *(const GPTHeader*)lba1.data();
if (!is_valid_gpt_header(header, sector_size()))
@ -171,7 +169,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.span()));
TRY(read_sectors(header.partition_entry_lba, size / sector_size(), entry_array.data()));
if (!is_valid_gpt_crc32(header, lba1, entry_array))
return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader);
@ -228,9 +226,8 @@ namespace Kernel
memcpy(m_label, label, sizeof(m_label));
}
BAN::ErrorOr<void> Partition::read_sectors(uint64_t lba, uint8_t sector_count, BAN::ByteSpan buffer)
BAN::ErrorOr<void> Partition::read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* 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);
@ -238,9 +235,8 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> Partition::write_sectors(uint64_t lba, uint8_t sector_count, BAN::ConstByteSpan buffer)
BAN::ErrorOr<void> Partition::write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* 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);
@ -248,23 +244,23 @@ namespace Kernel
return {};
}
BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, void* buffer, size_t bytes)
{
ASSERT(offset >= 0);
if (offset % m_device.sector_size() || buffer.size() % m_device.sector_size())
if (offset % m_device.sector_size() || bytes % 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 = buffer.size() / m_device.sector_size();
uint32_t sector_count = bytes / 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, buffer));
TRY(read_sectors(lba, sector_count, (uint8_t*)buffer));
return sector_count * m_device.sector_size();
}
@ -287,51 +283,36 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> StorageDevice::read_sectors(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
BAN::ErrorOr<void> StorageDevice::read_sectors(uint64_t lba, uint64_t sector_count, uint8_t* 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());
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);
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);
}
return {};
}
BAN::ErrorOr<void> StorageDevice::write_sectors(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
BAN::ErrorOr<void> StorageDevice::write_sectors(uint64_t lba, uint64_t sector_count, const uint8_t* buffer)
{
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);
}
// TODO: use disk cache for dirty pages. I don't wanna think about how to do it safely now
for (uint8_t offset = 0; offset < sector_count; offset++)
{
LockGuard _(m_lock);
Thread::TerminateBlocker blocker(Thread::current());
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));
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));
}
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, BAN::ByteSpan::from(event)));
size_t read = MUST(inode->read(0, &event, sizeof(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, BAN::ByteSpan buffer)
BAN::ErrorOr<size_t> TTY::read_impl(off_t, void* buffer, size_t count)
{
LockGuard _(m_lock);
while (!m_output.flush)
@ -314,8 +314,8 @@ namespace Kernel
return 0;
}
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_output.bytes);
memcpy(buffer.data(), m_output.buffer.data(), to_copy);
size_t to_copy = BAN::Math::min<size_t>(count, m_output.bytes);
memcpy(buffer, 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, BAN::ConstByteSpan buffer)
BAN::ErrorOr<size_t> TTY::write_impl(off_t, const void* buffer, size_t count)
{
LockGuard _(m_lock);
for (size_t i = 0; i < buffer.size(); i++)
putchar(buffer[i]);
return buffer.size();
for (size_t i = 0; i < count; i++)
putchar(((uint8_t*)buffer)[i]);
return count;
}
bool TTY::has_data_impl() const

19
qemu.sh Executable file
View File

@ -0,0 +1,19 @@
#!/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

@ -1,107 +0,0 @@
#!/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

View File

@ -1,14 +0,0 @@
#!/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

View File

@ -1,27 +0,0 @@
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,45 +0,0 @@
#!/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

View File

@ -1,24 +0,0 @@
#!/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 \
$@ \

View File

@ -1,18 +0,0 @@
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"
if [[ -z $BANAN_SYSROOT ]]; then
echo "You must set the BANAN_SYSROOT environment variable" >&2
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
exit 1
fi
if [[ -z $BANAN_TOOLCHAIN_DIR ]]; then
echo "You must set the BANAN_TOOLCHAIN_DIR environment variable" >&2
if [[ -z $PREFIX ]]; then
echo "You must set the PREFIX environment variable" >&2
exit 1
fi
if [[ -z $BANAN_TOOLCHAIN_PREFIX ]]; then
echo "You must set the BANAN_TOOLCHAIN_PREFIX environment variable" >&2
if [[ -z $ARCH ]]; then
echo "You must set the ARCH environment variable" >&2
exit 1
fi
if [[ -z $BANAN_TOOLCHAIN_TRIPLE_PREFIX ]]; then
echo "You must set the BANAN_TOOLCHAIN_TRIPLE_PREFIX environment variable" >&2
exit 1
fi
TARGET="${ARCH}-banan_os"
if [[ -z $BANAN_ARCH ]]; then
echo "You must set the BANAN_ARCH environment variable" >&2
exit 1
fi
if [ ! -f ${PREFIX}/bin/${TARGET}-ld ]; then
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,24 +45,26 @@ build_binutils () {
fi
mkdir -p build/${BINUTILS_VERSION}/
cd build/${BINUTILS_VERSION}/
pushd build/${BINUTILS_VERSION}/
../../${BINUTILS_VERSION}/configure \
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
--with-sysroot="$BANAN_SYSROOT" \
--target="$TARGET" \
--prefix="$PREFIX" \
--with-sysroot="$SYSROOT" \
--disable-nls \
--disable-werror
make -j $(nproc)
make install
}
build_gcc () {
popd
fi
if [ ! -f ${PREFIX}/bin/${TARGET}-g++ ]; then
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
@ -73,25 +75,27 @@ build_gcc () {
fi
mkdir -p build/${GCC_VERSION}/
cd build/${GCC_VERSION}/
pushd build/${GCC_VERSION}/
../../${GCC_VERSION}/configure \
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
--with-sysroot="$BANAN_SYSROOT" \
--target="$TARGET" \
--prefix="$PREFIX" \
--with-sysroot="$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
}
build_grub () {
popd
fi
if [ ! -f ${PREFIX}/bin/grub-mkstandalone ]; then
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
@ -101,29 +105,17 @@ build_grub () {
fi
mkdir -p build/${GRUB_VERSION}/
cd build/${GRUB_VERSION}/
pushd build/${GRUB_VERSION}/
../../${GRUB_VERSION}/configure \
--target="$BANAN_ARCH" \
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
--target="$ARCH" \
--prefix="$PREFIX" \
--with-platform="efi" \
--disable-werror
make -j $(nproc)
make install
}
build_libstdcpp () {
cd build/${GCC_VERSION}/
make -j $(nproc) all-target-libstdc++-v3
make install-target-libstdc++-v3
}
popd
if [[ "$1" == "libstdc++" ]]; then
build_libstdcpp
exit 0
fi
build_binutils
build_gcc
build_grub

View File

@ -1 +0,0 @@
*/