Compare commits
No commits in common. "00ee86920a73ca91333f84e58a74b30529eb9905" and "e2e5c31d54d398e55944269f4d684961f8d48835" have entirely different histories.
00ee86920a
...
e2e5c31d54
|
@ -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>;
|
|
||||||
|
|
||||||
}
|
|
|
@ -43,8 +43,6 @@ namespace BAN
|
||||||
|
|
||||||
Span slice(size_type, size_type = ~size_type(0));
|
Span slice(size_type, size_type = ~size_type(0));
|
||||||
|
|
||||||
Span<const T> as_const() const { return Span<const T>(m_data, m_size); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* m_data = nullptr;
|
T* m_data = nullptr;
|
||||||
size_type m_size = 0;
|
size_type m_size = 0;
|
||||||
|
|
|
@ -1,13 +1,35 @@
|
||||||
cmake_minimum_required(VERSION 3.26)
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
|
||||||
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "banan-os")
|
if(DEFINED ENV{BANAN_ARCH})
|
||||||
message(FATAL_ERROR "CMAKE_SYSTEM_NAME is not banan-os")
|
set(BANAN_ARCH $ENV{BANAN_ARCH})
|
||||||
endif ()
|
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_options(-mno-sse -mno-sse2)
|
||||||
add_compile_definitions(__enable_sse=0)
|
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_BASE_SYSROOT ${CMAKE_SOURCE_DIR}/base-sysroot.tar.gz)
|
||||||
set(BANAN_SYSROOT ${CMAKE_BINARY_DIR}/sysroot)
|
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_LIB ${BANAN_SYSROOT}/usr/lib)
|
||||||
set(BANAN_BIN ${BANAN_SYSROOT}/usr/bin)
|
set(BANAN_BIN ${BANAN_SYSROOT}/usr/bin)
|
||||||
set(BANAN_BOOT ${BANAN_SYSROOT}/boot)
|
set(BANAN_BOOT ${BANAN_SYSROOT}/boot)
|
||||||
|
set(DISK_IMAGE_PATH ${CMAKE_BINARY_DIR}/banan-os.img)
|
||||||
|
|
||||||
add_subdirectory(kernel)
|
add_subdirectory(kernel)
|
||||||
add_subdirectory(BAN)
|
add_subdirectory(BAN)
|
||||||
|
@ -35,10 +58,63 @@ add_custom_target(headers
|
||||||
DEPENDS libelf-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 kernel-install
|
||||||
DEPENDS ban-install
|
DEPENDS ban-install
|
||||||
DEPENDS libc-install
|
DEPENDS libc-install
|
||||||
DEPENDS userspace-install
|
DEPENDS userspace-install
|
||||||
DEPENDS libelf-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
|
||||||
)
|
)
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace LibELF
|
||||||
return BAN::Error::from_errno(ENOEXEC);
|
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));
|
ASSERT(nread == sizeof(m_file_header));
|
||||||
|
|
||||||
if (m_file_header.e_ident[EI_MAG0] != ELFMAG0 ||
|
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));
|
TRY(m_program_headers.resize(m_file_header.e_phnum));
|
||||||
for (size_t i = 0; i < m_file_header.e_phnum; i++)
|
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];
|
const auto& pheader = m_program_headers[i];
|
||||||
if (pheader.p_type != PT_NULL && pheader.p_type != PT_LOAD)
|
if (pheader.p_type != PT_NULL && pheader.p_type != PT_LOAD)
|
||||||
|
@ -242,7 +242,7 @@ namespace LibELF
|
||||||
file_offset = vaddr - program_header.p_vaddr;
|
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);
|
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 {};
|
return {};
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
set(CMAKE_GENERATOR "Ninja" CACHE INTERNAL "" FORCE)
|
33
README.md
33
README.md
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# banan-os
|
# 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)
|
![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.
|
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.
|
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.
|
> ***NOTE:*** The following step has to be done only once. This might take a long time since we are compiling binutils and gcc.
|
||||||
```sh
|
```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
|
```sh
|
||||||
./script/build.sh qemu
|
ninja qemu
|
||||||
./script/build.sh qemu-nographic
|
ninja bochs
|
||||||
./script/build.sh qemu-debug
|
|
||||||
./script/build.sh bochs
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also build the kernel or disk image without running it:
|
You can also build the kernel or disk image without running it:
|
||||||
```sh
|
```sh
|
||||||
./script/build.sh kernel
|
ninja kernel
|
||||||
./script/build.sh image
|
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
|
```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
|
### Contributing
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ COM1_DEVICE=$(cat $COM1_DEVICE_FILE)
|
||||||
rm $COM1_DEVICE_FILE
|
rm $COM1_DEVICE_FILE
|
||||||
|
|
||||||
cat > $BOCHS_CONFIG_FILE << EOF
|
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
|
boot: disk
|
||||||
clock: sync=realtime, time0=local
|
clock: sync=realtime, time0=local
|
||||||
display_library: x, options="gui_debug"
|
display_library: x, options="gui_debug"
|
|
@ -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
|
|
@ -1,34 +1,14 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
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]
|
DISK_SIZE=$[50 * 1024 * 1024]
|
||||||
MOUNT_DIR=/mnt
|
MOUNT_DIR=/mnt
|
||||||
|
|
||||||
truncate -s 0 "$BANAN_DISK_IMAGE_PATH"
|
truncate -s 0 "$DISK_IMAGE_PATH"
|
||||||
truncate -s $DISK_SIZE "$BANAN_DISK_IMAGE_PATH"
|
truncate -s $DISK_SIZE "$DISK_IMAGE_PATH"
|
||||||
|
|
||||||
if [ "$BANAN_UEFI_BOOT" == "1" ]; then
|
if [ "$UEFI_BOOT" == "1" ]; then
|
||||||
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
|
g # gpt
|
||||||
n # new partition
|
n # new partition
|
||||||
1 # partition number 1
|
1 # partition number 1
|
||||||
|
@ -47,7 +27,7 @@ if [ "$BANAN_UEFI_BOOT" == "1" ]; then
|
||||||
w # write changes
|
w # write changes
|
||||||
EOF
|
EOF
|
||||||
else
|
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
|
g # gpt
|
||||||
n # new partition
|
n # new partition
|
||||||
1 # partition number 1
|
1 # partition number 1
|
||||||
|
@ -67,30 +47,30 @@ else
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
LOOP_DEV=$(sudo losetup -f --show "$BANAN_DISK_IMAGE_PATH")
|
LOOP_DEV=$(sudo losetup -f --show "$DISK_IMAGE_PATH")
|
||||||
sudo partprobe $LOOP_DEV
|
sudo partprobe $LOOP_DEV
|
||||||
|
|
||||||
PARTITION1=${LOOP_DEV}p1
|
PARTITION1=${LOOP_DEV}p1
|
||||||
PARTITION2=${LOOP_DEV}p2
|
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 mkfs.fat $PARTITION1 > /dev/null
|
||||||
sudo mount $PARTITION1 "$MOUNT_DIR"
|
sudo mount $PARTITION1 "$MOUNT_DIR"
|
||||||
sudo mkdir -p "$MOUNT_DIR/EFI/BOOT"
|
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 umount "$MOUNT_DIR"
|
||||||
|
|
||||||
sudo mount $PARTITION2 "$MOUNT_DIR"
|
sudo mount $PARTITION2 "$MOUNT_DIR"
|
||||||
sudo mkdir -p "$MOUNT_DIR/boot/grub"
|
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"
|
sudo umount "$MOUNT_DIR"
|
||||||
else
|
else
|
||||||
sudo mount $PARTITION2 "$MOUNT_DIR"
|
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 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 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"
|
sudo umount "$MOUNT_DIR"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -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
|
|
@ -20,8 +20,8 @@ namespace Kernel
|
||||||
, m_rdev(rdev)
|
, m_rdev(rdev)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return 0; }
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override { return 0; }
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return buffer.size(); };
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t size) override { return size; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|
|
@ -18,8 +18,8 @@ namespace Kernel
|
||||||
, m_rdev(rdev)
|
, m_rdev(rdev)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
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;
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return buffer.size(); };
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t size) override { return size; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|
|
@ -33,9 +33,6 @@ namespace Kernel
|
||||||
uint8_t* data() { return m_buffer.data(); }
|
uint8_t* data() { return m_buffer.data(); }
|
||||||
const uint8_t* data() const { 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) { return m_buffer[index]; }
|
||||||
uint8_t operator[](size_t index) const { return m_buffer[index]; }
|
uint8_t operator[](size_t index) const { return m_buffer[index]; }
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,8 @@ namespace Kernel
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
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> read_impl(off_t, void*, size_t) override;
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
||||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/ByteSpan.h>
|
|
||||||
#include <BAN/RefPtr.h>
|
#include <BAN/RefPtr.h>
|
||||||
#include <BAN/String.h>
|
#include <BAN/String.h>
|
||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
#include <BAN/Vector.h>
|
|
||||||
#include <BAN/WeakPtr.h>
|
#include <BAN/WeakPtr.h>
|
||||||
|
#include <BAN/Vector.h>
|
||||||
|
|
||||||
#include <kernel/API/DirectoryEntry.h>
|
#include <kernel/API/DirectoryEntry.h>
|
||||||
#include <kernel/Credentials.h>
|
#include <kernel/Credentials.h>
|
||||||
|
@ -96,8 +95,8 @@ namespace Kernel
|
||||||
BAN::ErrorOr<BAN::String> link_target();
|
BAN::ErrorOr<BAN::String> link_target();
|
||||||
|
|
||||||
// General API
|
// General API
|
||||||
BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer);
|
BAN::ErrorOr<size_t> read(off_t, void*, size_t);
|
||||||
BAN::ErrorOr<size_t> write(off_t, BAN::ConstByteSpan buffer);
|
BAN::ErrorOr<size_t> write(off_t, const void*, size_t);
|
||||||
BAN::ErrorOr<void> truncate(size_t);
|
BAN::ErrorOr<void> truncate(size_t);
|
||||||
bool has_data() const;
|
bool has_data() const;
|
||||||
|
|
||||||
|
@ -112,8 +111,8 @@ namespace Kernel
|
||||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
|
|
||||||
// General API
|
// General API
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) { 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, BAN::ConstByteSpan) { 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 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; }
|
virtual bool has_data_impl() const { dwarnln("nonblock not supported"); return true; }
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,8 @@ namespace Kernel
|
||||||
virtual dev_t rdev() const override { return 0; } // FIXME
|
virtual dev_t rdev() const override { return 0; } // FIXME
|
||||||
|
|
||||||
protected:
|
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;
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pipe(const Credentials&);
|
Pipe(const Credentials&);
|
||||||
|
|
|
@ -23,23 +23,23 @@ namespace Kernel
|
||||||
class ProcROInode final : public RamInode
|
class ProcROInode final : public RamInode
|
||||||
{
|
{
|
||||||
public:
|
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;
|
~ProcROInode() = default;
|
||||||
|
|
||||||
protected:
|
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
|
// 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 BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); }
|
||||||
virtual bool has_data_impl() const override { return true; }
|
virtual bool has_data_impl() const override { return true; }
|
||||||
|
|
||||||
private:
|
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:
|
private:
|
||||||
Process& m_process;
|
Process& m_process;
|
||||||
size_t (Process::*m_callback)(off_t, BAN::ByteSpan) const;
|
size_t (Process::*m_callback)(off_t, void*, size_t) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,8 +70,8 @@ namespace Kernel
|
||||||
protected:
|
protected:
|
||||||
RamFileInode(RamFileSystem&, const FullInodeInfo&);
|
RamFileInode(RamFileSystem&, const FullInodeInfo&);
|
||||||
|
|
||||||
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;
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
||||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace Kernel::Input
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
virtual dev_t rdev() const override { return m_rdev; }
|
||||||
|
|
||||||
protected:
|
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:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|
|
@ -41,8 +41,8 @@ namespace Kernel
|
||||||
void close_all();
|
void close_all();
|
||||||
void close_cloexec();
|
void close_cloexec();
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> read(int fd, BAN::ByteSpan);
|
BAN::ErrorOr<size_t> read(int fd, void* buffer, size_t count);
|
||||||
BAN::ErrorOr<size_t> write(int fd, BAN::ConstByteSpan);
|
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);
|
BAN::ErrorOr<void> read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size);
|
||||||
|
|
||||||
|
|
|
@ -139,9 +139,9 @@ namespace Kernel
|
||||||
|
|
||||||
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::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_meminfo(off_t offset, void* buffer, size_t buffer_size) const;
|
||||||
size_t proc_cmdline(off_t offset, BAN::ByteSpan) const;
|
size_t proc_cmdline(off_t offset, void* buffer, size_t buffer_size) const;
|
||||||
size_t proc_environ(off_t offset, BAN::ByteSpan) const;
|
size_t proc_environ(off_t offset, void* buffer, size_t buffer_size) const;
|
||||||
|
|
||||||
bool is_userspace() const { return m_is_userspace; }
|
bool is_userspace() const { return m_is_userspace; }
|
||||||
const userspace_info_t& userspace_info() const { return m_userspace_info; }
|
const userspace_info_t& userspace_info() const { return m_userspace_info; }
|
||||||
|
|
|
@ -23,15 +23,14 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> rebase();
|
BAN::ErrorOr<void> rebase();
|
||||||
BAN::ErrorOr<void> read_identify_data();
|
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> 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, BAN::ConstByteSpan) 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::ErrorOr<void> send_command_and_block(uint64_t lba, uint64_t sector_count, Command command);
|
||||||
|
|
||||||
BAN::Optional<uint32_t> find_free_command_slot();
|
BAN::Optional<uint32_t> find_free_command_slot();
|
||||||
|
|
||||||
void handle_irq();
|
void handle_irq();
|
||||||
|
void block_until_irq();
|
||||||
BAN::ErrorOr<void> block_until_command_completed(uint32_t command_slot);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::RefPtr<AHCIController> m_controller;
|
BAN::RefPtr<AHCIController> m_controller;
|
||||||
|
@ -42,6 +41,8 @@ namespace Kernel
|
||||||
// TODO: can we read straight to user buffer?
|
// TODO: can we read straight to user buffer?
|
||||||
BAN::UniqPtr<DMARegion> m_data_dma_region;
|
BAN::UniqPtr<DMARegion> m_data_dma_region;
|
||||||
|
|
||||||
|
volatile bool m_has_got_irq { false };
|
||||||
|
|
||||||
friend class AHCIController;
|
friend class AHCIController;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/ByteSpan.h>
|
|
||||||
#include <BAN/RefPtr.h>
|
#include <BAN/RefPtr.h>
|
||||||
#include <BAN/Vector.h>
|
#include <BAN/Vector.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
|
@ -23,8 +22,8 @@ namespace Kernel
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<ATABus>> create(uint16_t base, uint16_t ctrl, uint8_t irq);
|
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> read(ATADevice&, uint64_t, uint8_t, uint8_t*);
|
||||||
BAN::ErrorOr<void> write(ATADevice&, uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan);
|
BAN::ErrorOr<void> write(ATADevice&, uint64_t, uint8_t, const uint8_t*);
|
||||||
|
|
||||||
virtual void handle_irq() override;
|
virtual void handle_irq() override;
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ namespace Kernel
|
||||||
|
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
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> read_impl(off_t, void*, size_t) override;
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ATABaseDevice();
|
ATABaseDevice();
|
||||||
|
@ -63,8 +63,8 @@ namespace Kernel
|
||||||
private:
|
private:
|
||||||
ATADevice(BAN::RefPtr<ATABus>, ATABus::DeviceType, bool is_secodary);
|
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> read_sectors_impl(uint64_t, uint64_t, uint8_t*) override;
|
||||||
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t, uint64_t, BAN::ConstByteSpan) override;
|
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t, uint64_t, const uint8_t*) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::RefPtr<ATABus> m_bus;
|
BAN::RefPtr<ATABus> m_bus;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/Array.h>
|
#include <BAN/Array.h>
|
||||||
#include <BAN/ByteSpan.h>
|
|
||||||
#include <kernel/Memory/Types.h>
|
#include <kernel/Memory/Types.h>
|
||||||
#include <kernel/SpinLock.h>
|
#include <kernel/SpinLock.h>
|
||||||
|
|
||||||
|
@ -16,8 +15,8 @@ namespace Kernel
|
||||||
DiskCache(size_t sector_size, StorageDevice&);
|
DiskCache(size_t sector_size, StorageDevice&);
|
||||||
~DiskCache();
|
~DiskCache();
|
||||||
|
|
||||||
bool read_from_cache(uint64_t sector, BAN::ByteSpan);
|
bool read_from_cache(uint64_t sector, uint8_t* buffer);
|
||||||
BAN::ErrorOr<void> write_to_cache(uint64_t sector, BAN::ConstByteSpan, bool dirty);
|
BAN::ErrorOr<void> write_to_cache(uint64_t sector, const uint8_t* buffer, bool dirty);
|
||||||
|
|
||||||
BAN::ErrorOr<void> sync();
|
BAN::ErrorOr<void> sync();
|
||||||
size_t release_clean_pages(size_t);
|
size_t release_clean_pages(size_t);
|
||||||
|
|
|
@ -30,8 +30,8 @@ namespace Kernel
|
||||||
const char* label() const { return m_label; }
|
const char* label() const { return m_label; }
|
||||||
const StorageDevice& device() const { return m_device; }
|
const StorageDevice& device() const { return m_device; }
|
||||||
|
|
||||||
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint8_t sector_count, BAN::ByteSpan);
|
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, BAN::ConstByteSpan);
|
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; }
|
virtual BAN::StringView name() const override { return m_name; }
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ namespace Kernel
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
virtual dev_t rdev() const override { return m_rdev; }
|
||||||
|
|
||||||
protected:
|
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:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
@ -73,8 +73,8 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> initialize_partitions();
|
BAN::ErrorOr<void> initialize_partitions();
|
||||||
|
|
||||||
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint64_t sector_count, BAN::ByteSpan);
|
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, BAN::ConstByteSpan);
|
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint64_t sector_count, const uint8_t* buffer);
|
||||||
|
|
||||||
virtual uint32_t sector_size() const = 0;
|
virtual uint32_t sector_size() const = 0;
|
||||||
virtual uint64_t total_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; }
|
virtual bool is_storage_device() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan) = 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, BAN::ConstByteSpan) = 0;
|
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t lba, uint64_t sector_count, const uint8_t* buffer) = 0;
|
||||||
void add_disk_cache();
|
void add_disk_cache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -49,8 +49,8 @@ namespace Kernel
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void putchar_impl(uint8_t ch) = 0;
|
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> read_impl(off_t, void*, size_t) override;
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void do_backspace();
|
void do_backspace();
|
||||||
|
|
|
@ -12,10 +12,10 @@ namespace Kernel
|
||||||
return BAN::RefPtr<ZeroDevice>::adopt(result);
|
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());
|
memset(buffer, 0, bytes);
|
||||||
return buffer.size();
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -33,7 +33,7 @@ namespace Kernel
|
||||||
BAN::Vector<uint8_t> superblock_buffer;
|
BAN::Vector<uint8_t> superblock_buffer;
|
||||||
TRY(superblock_buffer.resize(sector_count * sector_size));
|
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));
|
memcpy(&m_superblock, superblock_buffer.data(), sizeof(Ext2::Superblock));
|
||||||
}
|
}
|
||||||
|
@ -223,7 +223,7 @@ namespace Kernel
|
||||||
|
|
||||||
ASSERT(block >= 2);
|
ASSERT(block >= 2);
|
||||||
ASSERT(buffer.size() >= block_size);
|
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)
|
void Ext2FS::write_block(uint32_t block, const BlockBufferWrapper& buffer)
|
||||||
|
@ -237,7 +237,7 @@ namespace Kernel
|
||||||
|
|
||||||
ASSERT(block >= 2);
|
ASSERT(block >= 2);
|
||||||
ASSERT(buffer.size() >= block_size);
|
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()
|
void Ext2FS::sync_superblock()
|
||||||
|
@ -258,11 +258,11 @@ namespace Kernel
|
||||||
BAN::Vector<uint8_t> superblock_buffer;
|
BAN::Vector<uint8_t> superblock_buffer;
|
||||||
MUST(superblock_buffer.resize(sector_count * sector_size));
|
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))
|
if (memcmp(superblock_buffer.data(), &m_superblock, superblock_bytes))
|
||||||
{
|
{
|
||||||
memcpy(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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,21 +100,19 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
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
|
// FIXME: update atime if needed
|
||||||
|
|
||||||
ASSERT(!mode().ifdir());
|
ASSERT(!mode().ifdir());
|
||||||
ASSERT(offset >= 0);
|
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);
|
return BAN::Error::from_errno(EOVERFLOW);
|
||||||
|
|
||||||
if (offset >= m_inode.size)
|
if (offset >= m_inode.size)
|
||||||
return 0;
|
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;
|
count = m_inode.size - offset;
|
||||||
|
|
||||||
const uint32_t block_size = blksize();
|
const uint32_t block_size = blksize();
|
||||||
|
@ -133,7 +131,7 @@ namespace Kernel
|
||||||
|
|
||||||
uint32_t copy_offset = (offset + n_read) % block_size;
|
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);
|
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;
|
n_read += to_copy;
|
||||||
}
|
}
|
||||||
|
@ -141,25 +139,26 @@ namespace Kernel
|
||||||
return n_read;
|
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
|
// FIXME: update atime if needed
|
||||||
|
|
||||||
ASSERT(!mode().ifdir());
|
ASSERT(!mode().ifdir());
|
||||||
ASSERT(offset >= 0);
|
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);
|
return BAN::Error::from_errno(EOVERFLOW);
|
||||||
|
|
||||||
if (m_inode.size < offset + buffer.size())
|
if (m_inode.size < offset + count)
|
||||||
TRY(truncate_impl(offset + buffer.size()));
|
TRY(truncate_impl(offset + count));
|
||||||
|
|
||||||
const uint32_t block_size = blksize();
|
const uint32_t block_size = blksize();
|
||||||
|
|
||||||
auto block_buffer = m_fs.get_block_buffer();
|
auto block_buffer = m_fs.get_block_buffer();
|
||||||
|
|
||||||
size_t written = 0;
|
const uint8_t* u8buffer = (const uint8_t*)buffer;
|
||||||
size_t to_write = buffer.size();
|
|
||||||
|
size_t to_write = count;
|
||||||
|
|
||||||
// Write partial block
|
// Write partial block
|
||||||
if (offset % block_size)
|
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);
|
uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - block_offset, to_write);
|
||||||
|
|
||||||
m_fs.read_block(block_index, block_buffer);
|
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);
|
m_fs.write_block(block_index, block_buffer);
|
||||||
|
|
||||||
written += to_copy;
|
u8buffer += to_copy;
|
||||||
offset += to_copy;
|
offset += to_copy;
|
||||||
to_write -= 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);
|
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);
|
m_fs.write_block(block_index, block_buffer);
|
||||||
|
|
||||||
written += block_size;
|
u8buffer += block_size;
|
||||||
offset += block_size;
|
offset += block_size;
|
||||||
to_write -= 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);
|
uint32_t block_index = fs_block_of_data_block_index(offset / block_size);
|
||||||
|
|
||||||
m_fs.read_block(block_index, block_buffer);
|
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);
|
m_fs.write_block(block_index, block_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.size();
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::truncate_impl(size_t new_size)
|
BAN::ErrorOr<void> Ext2Inode::truncate_impl(size_t new_size)
|
||||||
|
|
|
@ -102,22 +102,22 @@ namespace Kernel
|
||||||
return link_target_impl();
|
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);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
Thread::TerminateBlocker blocker(Thread::current());
|
||||||
if (mode().ifdir())
|
if (mode().ifdir())
|
||||||
return BAN::Error::from_errno(EISDIR);
|
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);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
Thread::TerminateBlocker blocker(Thread::current());
|
||||||
if (mode().ifdir())
|
if (mode().ifdir())
|
||||||
return BAN::Error::from_errno(EISDIR);
|
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)
|
BAN::ErrorOr<void> Inode::truncate(size_t size)
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace Kernel
|
||||||
m_semaphore.unblock();
|
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);
|
LockGuard _(m_lock);
|
||||||
while (m_buffer.empty())
|
while (m_buffer.empty())
|
||||||
|
@ -51,8 +51,8 @@ namespace Kernel
|
||||||
m_lock.lock();
|
m_lock.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer.size());
|
size_t to_copy = BAN::Math::min<size_t>(count, m_buffer.size());
|
||||||
memcpy(buffer.data(), m_buffer.data(), to_copy);
|
memcpy(buffer, m_buffer.data(), to_copy);
|
||||||
|
|
||||||
memmove(m_buffer.data(), m_buffer.data() + to_copy, m_buffer.size() - 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));
|
MUST(m_buffer.resize(m_buffer.size() - to_copy));
|
||||||
|
@ -64,14 +64,14 @@ namespace Kernel
|
||||||
return to_copy;
|
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);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
size_t old_size = m_buffer.size();
|
size_t old_size = m_buffer.size();
|
||||||
|
|
||||||
TRY(m_buffer.resize(old_size + buffer.size()));
|
TRY(m_buffer.resize(old_size + count));
|
||||||
memcpy(m_buffer.data() + old_size, buffer.data(), buffer.size());
|
memcpy(m_buffer.data() + old_size, buffer, count);
|
||||||
|
|
||||||
timespec current_time = SystemTimer::get().real_time();
|
timespec current_time = SystemTimer::get().real_time();
|
||||||
m_mtime = current_time;
|
m_mtime = current_time;
|
||||||
|
@ -79,7 +79,7 @@ namespace Kernel
|
||||||
|
|
||||||
m_semaphore.unblock();
|
m_semaphore.unblock();
|
||||||
|
|
||||||
return buffer.size();
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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);
|
FullInodeInfo inode_info(fs, mode, uid, gid);
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ namespace Kernel
|
||||||
return BAN::RefPtr<ProcROInode>::adopt(inode_ptr);
|
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)
|
: RamInode(fs, inode_info)
|
||||||
, m_process(process)
|
, m_process(process)
|
||||||
, m_callback(callback)
|
, m_callback(callback)
|
||||||
|
@ -43,12 +43,12 @@ namespace Kernel
|
||||||
m_inode_info.mode |= Inode::Mode::IFREG;
|
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);
|
ASSERT(offset >= 0);
|
||||||
if ((size_t)offset >= sizeof(proc_meminfo_t))
|
if ((size_t)offset >= sizeof(proc_meminfo_t))
|
||||||
return 0;
|
return 0;
|
||||||
return (m_process.*m_callback)(offset, buffer);
|
return (m_process.*m_callback)(offset, buffer, buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,23 +48,23 @@ namespace Kernel
|
||||||
m_inode_info.mode |= Inode::Mode::IFREG;
|
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);
|
ASSERT(offset >= 0);
|
||||||
if (offset >= size())
|
if (offset >= size())
|
||||||
return 0;
|
return 0;
|
||||||
size_t to_copy = BAN::Math::min<size_t>(m_inode_info.size - offset, buffer.size());
|
size_t to_copy = BAN::Math::min<size_t>(m_inode_info.size - offset, bytes);
|
||||||
memcpy(buffer.data(), m_data.data(), to_copy);
|
memcpy(buffer, m_data.data(), to_copy);
|
||||||
return 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);
|
ASSERT(offset >= 0);
|
||||||
if (offset + buffer.size() > (size_t)size())
|
if (offset + bytes > (size_t)size())
|
||||||
TRY(truncate_impl(offset + buffer.size()));
|
TRY(truncate_impl(offset + bytes));
|
||||||
memcpy(m_data.data() + offset, buffer.data(), buffer.size());
|
memcpy(m_data.data() + offset, buffer, bytes);
|
||||||
return buffer.size();
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> RamFileInode::truncate_impl(size_t new_size)
|
BAN::ErrorOr<void> RamFileInode::truncate_impl(size_t new_size)
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace Kernel
|
||||||
BAN::Vector<uint8_t> file_data;
|
BAN::Vector<uint8_t> file_data;
|
||||||
TRY(file_data.resize(inode->size()));
|
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)
|
if (file_data.size() < 4)
|
||||||
return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall);
|
return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall);
|
||||||
|
|
|
@ -217,9 +217,9 @@ namespace Kernel::Input
|
||||||
append_command_queue(Command::SET_LEDS, new_leds);
|
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);
|
return BAN::Error::from_errno(ENOBUFS);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -231,7 +231,7 @@ namespace Kernel::Input
|
||||||
if (m_event_queue.empty())
|
if (m_event_queue.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
buffer.as<KeyEvent>() = m_event_queue.front();
|
*(KeyEvent*)buffer = m_event_queue.front();
|
||||||
m_event_queue.pop();
|
m_event_queue.pop();
|
||||||
|
|
||||||
return sizeof(KeyEvent);
|
return sizeof(KeyEvent);
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace Kernel
|
||||||
page_table.unmap_page(0);
|
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());
|
dwarnln("{}", ret.error());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ namespace Kernel
|
||||||
|
|
||||||
// Zero out the new page
|
// Zero out the new page
|
||||||
if (&PageTable::current() == &m_page_table)
|
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
|
else
|
||||||
{
|
{
|
||||||
auto& page_table = PageTable::current();
|
auto& page_table = PageTable::current();
|
||||||
|
@ -118,7 +118,7 @@ namespace Kernel
|
||||||
ASSERT(page_table.is_page_free(0));
|
ASSERT(page_table.is_page_free(0));
|
||||||
|
|
||||||
page_table.map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
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);
|
memset((void*)0, 0x00, PAGE_SIZE);
|
||||||
page_table.unmap_page(0);
|
page_table.unmap_page(0);
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ namespace Kernel
|
||||||
size_t offset = vaddr - m_vaddr;
|
size_t offset = vaddr - m_vaddr;
|
||||||
size_t bytes = BAN::Math::min<size_t>(m_size - offset, PAGE_SIZE);
|
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();
|
auto& page_table = PageTable::current();
|
||||||
|
|
||||||
|
|
|
@ -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));
|
TRY(validate_fd(fd));
|
||||||
auto& open_file = m_open_files[fd];
|
auto& open_file = m_open_files[fd];
|
||||||
if ((open_file->flags & O_NONBLOCK) && !open_file->inode->has_data())
|
if ((open_file->flags & O_NONBLOCK) && !open_file->inode->has_data())
|
||||||
return 0;
|
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;
|
open_file->offset += nread;
|
||||||
return 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));
|
TRY(validate_fd(fd));
|
||||||
auto& open_file = m_open_files[fd];
|
auto& open_file = m_open_files[fd];
|
||||||
if (open_file->flags & O_APPEND)
|
if (open_file->flags & O_APPEND)
|
||||||
open_file->offset = open_file->inode->size();
|
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;
|
open_file->offset += nwrite;
|
||||||
return nwrite;
|
return nwrite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,7 +260,7 @@ namespace Kernel
|
||||||
thread->set_terminating();
|
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);
|
ASSERT(offset >= 0);
|
||||||
if ((size_t)offset >= sizeof(proc_meminfo_t))
|
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());
|
size_t bytes = BAN::Math::min<size_t>(sizeof(proc_meminfo_t) - offset, buffer_size);
|
||||||
memcpy(buffer.data(), (uint8_t*)&meminfo + offset, bytes);
|
memcpy(buffer, (uint8_t*)&meminfo + offset, bytes);
|
||||||
return 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 offset = 0;
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
|
@ -307,11 +307,11 @@ namespace Kernel
|
||||||
if (offset < start)
|
if (offset < start)
|
||||||
elem_offset = start - offset;
|
elem_offset = start - offset;
|
||||||
|
|
||||||
size_t bytes = BAN::Math::min<size_t>(elem.size() + 1 - elem_offset, buffer.size() - written);
|
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);
|
memcpy((uint8_t*)buffer + written, elem.data() + elem_offset, bytes);
|
||||||
|
|
||||||
written += bytes;
|
written += bytes;
|
||||||
if (written >= buffer.size())
|
if (written >= buffer_size)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
offset += elem.size() + 1;
|
offset += elem.size() + 1;
|
||||||
|
@ -319,16 +319,16 @@ namespace Kernel
|
||||||
return written;
|
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);
|
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);
|
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)
|
BAN::ErrorOr<long> Process::sys_exit(int status)
|
||||||
|
@ -723,14 +723,14 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(buffer, count);
|
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)
|
BAN::ErrorOr<long> Process::sys_write(int fd, const void* buffer, size_t count)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(buffer, count);
|
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])
|
BAN::ErrorOr<long> Process::sys_pipe(int fildes[2])
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#include <kernel/Scheduler.h>
|
|
||||||
#include <kernel/Storage/ATA/AHCI/Controller.h>
|
#include <kernel/Storage/ATA/AHCI/Controller.h>
|
||||||
#include <kernel/Storage/ATA/AHCI/Device.h>
|
#include <kernel/Storage/ATA/AHCI/Device.h>
|
||||||
#include <kernel/Storage/ATA/ATADefinitions.h>
|
#include <kernel/Storage/ATA/ATADefinitions.h>
|
||||||
|
@ -41,7 +40,7 @@ namespace Kernel
|
||||||
m_port->ie = 0xFFFFFFFF;
|
m_port->ie = 0xFFFFFFFF;
|
||||||
|
|
||||||
TRY(read_identify_data());
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -121,7 +120,8 @@ namespace Kernel
|
||||||
|
|
||||||
m_port->ci = 1 << slot.value();
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -145,58 +145,41 @@ namespace Kernel
|
||||||
|
|
||||||
void AHCIDevice::handle_irq()
|
void AHCIDevice::handle_irq()
|
||||||
{
|
{
|
||||||
|
ASSERT(!m_has_got_irq);
|
||||||
uint16_t err = m_port->serr & 0xFFFF;
|
uint16_t err = m_port->serr & 0xFFFF;
|
||||||
if (err)
|
if (err)
|
||||||
print_error(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;
|
while (!__sync_bool_compare_and_swap(&m_has_got_irq, true, false))
|
||||||
static constexpr uint64_t poll_timeout_ms = 10;
|
__builtin_ia32_pause();
|
||||||
|
|
||||||
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();
|
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)
|
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);
|
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));
|
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 {};
|
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();
|
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)
|
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);
|
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));
|
TRY(send_command_and_block(lba + sector_off, to_read, Command::Write));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +258,8 @@ namespace Kernel
|
||||||
|
|
||||||
m_port->ci = 1 << slot.value();
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,10 +228,8 @@ namespace Kernel
|
||||||
return BAN::Error::from_error_code(ErrorCode::None);
|
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())
|
if (lba + sector_count > device.sector_count())
|
||||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||||
|
|
||||||
|
@ -253,7 +251,7 @@ namespace Kernel
|
||||||
for (uint32_t sector = 0; sector < sector_count; sector++)
|
for (uint32_t sector = 0; sector < sector_count; sector++)
|
||||||
{
|
{
|
||||||
block_until_irq();
|
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
|
else
|
||||||
|
@ -265,10 +263,8 @@ namespace Kernel
|
||||||
return {};
|
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())
|
if (lba + sector_count > device.sector_count())
|
||||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||||
|
|
||||||
|
@ -289,7 +285,7 @@ namespace Kernel
|
||||||
|
|
||||||
for (uint32_t sector = 0; sector < sector_count; sector++)
|
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();
|
block_until_irq();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,24 +82,24 @@ namespace Kernel
|
||||||
return {};
|
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())
|
if (offset % sector_size())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
if (buffer.size() % sector_size())
|
if (bytes % sector_size())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
TRY(read_sectors(offset / sector_size(), buffer.size() / sector_size(), buffer));
|
TRY(read_sectors(offset / sector_size(), bytes / sector_size(), (uint8_t*)buffer));
|
||||||
return buffer.size();
|
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())
|
if (offset % sector_size())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
if (buffer.size() % sector_size())
|
if (bytes % sector_size())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
TRY(write_sectors(offset / sector_size(), buffer.size() / sector_size(), buffer));
|
TRY(write_sectors(offset / sector_size(), bytes / sector_size(), (const uint8_t*)buffer));
|
||||||
return buffer.size();
|
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)
|
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)
|
, 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));
|
TRY(m_bus->read(*this, lba, sector_count, buffer));
|
||||||
return {};
|
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));
|
TRY(m_bus->write(*this, lba, sector_count, buffer));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,8 @@ namespace Kernel
|
||||||
release_all_pages();
|
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 sectors_per_page = PAGE_SIZE / m_sector_size;
|
||||||
uint64_t page_cache_offset = sector % sectors_per_page;
|
uint64_t page_cache_offset = sector % sectors_per_page;
|
||||||
uint64_t page_cache_start = sector - page_cache_offset;
|
uint64_t page_cache_start = sector - page_cache_offset;
|
||||||
|
@ -48,7 +46,7 @@ namespace Kernel
|
||||||
|
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
|
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);
|
page_table.unmap_page(0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -57,9 +55,8 @@ namespace Kernel
|
||||||
return false;
|
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 sectors_per_page = PAGE_SIZE / m_sector_size;
|
||||||
uint64_t page_cache_offset = sector % sectors_per_page;
|
uint64_t page_cache_offset = sector % sectors_per_page;
|
||||||
uint64_t page_cache_start = sector - page_cache_offset;
|
uint64_t page_cache_start = sector - page_cache_offset;
|
||||||
|
@ -83,7 +80,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
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);
|
page_table.unmap_page(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,8 +110,8 @@ namespace Kernel
|
||||||
|
|
||||||
{
|
{
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
page_table.map_page_at(cache.paddr, 0, 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);
|
page_table.unmap_page(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,8 +149,7 @@ namespace Kernel
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dprintln_if(DEBUG_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
|
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, m_sync_cache.data() + sector_start * m_sector_size));
|
||||||
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, data_slice));
|
|
||||||
sector_start += sector_count + 1;
|
sector_start += sector_count + 1;
|
||||||
sector_count = 0;
|
sector_count = 0;
|
||||||
}
|
}
|
||||||
|
@ -162,8 +158,7 @@ namespace Kernel
|
||||||
if (sector_count > 0)
|
if (sector_count > 0)
|
||||||
{
|
{
|
||||||
dprintln_if(DEBUG_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
|
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, m_sync_cache.data() + sector_start * m_sector_size));
|
||||||
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, data_slice));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.dirty_mask = 0;
|
cache.dirty_mask = 0;
|
||||||
|
|
|
@ -153,10 +153,8 @@ namespace Kernel
|
||||||
if (total_size() < sizeof(GPTHeader))
|
if (total_size() < sizeof(GPTHeader))
|
||||||
return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader);
|
return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader);
|
||||||
|
|
||||||
BAN::Vector<uint8_t> lba1;
|
BAN::Vector<uint8_t> lba1(sector_size());
|
||||||
TRY(lba1.resize(sector_size()));
|
TRY(read_sectors(1, 1, lba1.data()));
|
||||||
|
|
||||||
TRY(read_sectors(1, 1, lba1.span()));
|
|
||||||
|
|
||||||
const GPTHeader& header = *(const GPTHeader*)lba1.data();
|
const GPTHeader& header = *(const GPTHeader*)lba1.data();
|
||||||
if (!is_valid_gpt_header(header, sector_size()))
|
if (!is_valid_gpt_header(header, sector_size()))
|
||||||
|
@ -171,7 +169,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::Vector<uint8_t> entry_array;
|
BAN::Vector<uint8_t> entry_array;
|
||||||
TRY(entry_array.resize(size));
|
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))
|
if (!is_valid_gpt_crc32(header, lba1, entry_array))
|
||||||
return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader);
|
return BAN::Error::from_error_code(ErrorCode::Storage_GPTHeader);
|
||||||
|
@ -228,9 +226,8 @@ namespace Kernel
|
||||||
memcpy(m_label, label, sizeof(m_label));
|
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;
|
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
||||||
if (lba + sector_count > sectors_in_partition)
|
if (lba + sector_count > sectors_in_partition)
|
||||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||||
|
@ -238,9 +235,8 @@ namespace Kernel
|
||||||
return {};
|
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;
|
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
||||||
if (lba + sector_count > sectors_in_partition)
|
if (lba + sector_count > sectors_in_partition)
|
||||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||||
|
@ -248,23 +244,23 @@ namespace Kernel
|
||||||
return {};
|
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);
|
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);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
|
||||||
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
||||||
uint32_t lba = offset / m_device.sector_size();
|
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)
|
if (lba == sectors_in_partition)
|
||||||
return 0;
|
return 0;
|
||||||
if (lba + sector_count > sectors_in_partition)
|
if (lba + sector_count > sectors_in_partition)
|
||||||
sector_count = sectors_in_partition - lba;
|
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();
|
return sector_count * m_device.sector_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,51 +283,36 @@ namespace Kernel
|
||||||
return {};
|
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++)
|
for (uint64_t offset = 0; offset < sector_count; offset++)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
Thread::TerminateBlocker blocker(Thread::current());
|
||||||
|
|
||||||
auto sector_buffer = buffer.slice(offset * sector_size(), sector_size());
|
uint8_t* buffer_ptr = buffer + offset * sector_size();
|
||||||
if (m_disk_cache->read_from_cache(lba + offset, sector_buffer))
|
if (m_disk_cache.has_value())
|
||||||
|
if (m_disk_cache->read_from_cache(lba + offset, buffer_ptr))
|
||||||
continue;
|
continue;
|
||||||
TRY(read_sectors_impl(lba + offset, 1, sector_buffer));
|
TRY(read_sectors_impl(lba + offset, 1, buffer_ptr));
|
||||||
(void)m_disk_cache->write_to_cache(lba + offset, sector_buffer, false);
|
if (m_disk_cache.has_value())
|
||||||
|
(void)m_disk_cache->write_to_cache(lba + offset, buffer_ptr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
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());
|
// TODO: use disk cache for dirty pages. I don't wanna think about how to do it safely now
|
||||||
|
|
||||||
{
|
|
||||||
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++)
|
for (uint8_t offset = 0; offset < sector_count; offset++)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
Thread::TerminateBlocker blocker(Thread::current());
|
||||||
|
|
||||||
auto sector_buffer = buffer.slice(offset * sector_size(), sector_size());
|
const uint8_t* buffer_ptr = buffer + offset * sector_size();
|
||||||
if (m_disk_cache->write_to_cache(lba + offset, sector_buffer, true).is_error())
|
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, sector_buffer));
|
TRY(write_sectors_impl(lba + offset, 1, buffer_ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -95,7 +95,7 @@ namespace Kernel
|
||||||
TTY::current()->m_tty_ctrl.semaphore.block();
|
TTY::current()->m_tty_ctrl.semaphore.block();
|
||||||
|
|
||||||
Input::KeyEvent event;
|
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));
|
ASSERT(read == sizeof(event));
|
||||||
TTY::current()->on_key_event(event);
|
TTY::current()->on_key_event(event);
|
||||||
}
|
}
|
||||||
|
@ -298,7 +298,7 @@ namespace Kernel
|
||||||
putchar_impl(ch);
|
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);
|
LockGuard _(m_lock);
|
||||||
while (!m_output.flush)
|
while (!m_output.flush)
|
||||||
|
@ -314,8 +314,8 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_output.bytes);
|
size_t to_copy = BAN::Math::min<size_t>(count, m_output.bytes);
|
||||||
memcpy(buffer.data(), m_output.buffer.data(), to_copy);
|
memcpy(buffer, m_output.buffer.data(), to_copy);
|
||||||
|
|
||||||
memmove(m_output.buffer.data(), m_output.buffer.data() + to_copy, m_output.bytes - to_copy);
|
memmove(m_output.buffer.data(), m_output.buffer.data() + to_copy, m_output.bytes - to_copy);
|
||||||
m_output.bytes -= to_copy;
|
m_output.bytes -= to_copy;
|
||||||
|
@ -328,12 +328,12 @@ namespace Kernel
|
||||||
return to_copy;
|
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);
|
LockGuard _(m_lock);
|
||||||
for (size_t i = 0; i < buffer.size(); i++)
|
for (size_t i = 0; i < count; i++)
|
||||||
putchar(buffer[i]);
|
putchar(((uint8_t*)buffer)[i]);
|
||||||
return buffer.size();
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTY::has_data_impl() const
|
bool TTY::has_data_impl() const
|
||||||
|
|
|
@ -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 \
|
||||||
|
$@ \
|
107
script/build.sh
107
script/build.sh
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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 \
|
|
||||||
$@ \
|
|
|
@ -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)
|
|
|
@ -5,36 +5,36 @@ BINUTILS_VERSION="binutils-2.39"
|
||||||
GCC_VERSION="gcc-12.2.0"
|
GCC_VERSION="gcc-12.2.0"
|
||||||
GRUB_VERSION="grub-2.06"
|
GRUB_VERSION="grub-2.06"
|
||||||
|
|
||||||
if [[ -z $BANAN_SYSROOT ]]; then
|
cd $(dirname "$0")
|
||||||
echo "You must set the BANAN_SYSROOT environment variable" >&2
|
|
||||||
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z $BANAN_TOOLCHAIN_DIR ]]; then
|
if [[ -z $PREFIX ]]; then
|
||||||
echo "You must set the BANAN_TOOLCHAIN_DIR environment variable" >&2
|
echo "You must set the PREFIX environment variable" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z $BANAN_TOOLCHAIN_PREFIX ]]; then
|
if [[ -z $ARCH ]]; then
|
||||||
echo "You must set the BANAN_TOOLCHAIN_PREFIX environment variable" >&2
|
echo "You must set the ARCH environment variable" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z $BANAN_TOOLCHAIN_TRIPLE_PREFIX ]]; then
|
TARGET="${ARCH}-banan_os"
|
||||||
echo "You must set the BANAN_TOOLCHAIN_TRIPLE_PREFIX environment variable" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z $BANAN_ARCH ]]; then
|
if [ ! -f ${PREFIX}/bin/${TARGET}-ld ]; then
|
||||||
echo "You must set the BANAN_ARCH environment variable" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
build_binutils () {
|
|
||||||
echo "Building ${BINUTILS_VERSION}"
|
echo "Building ${BINUTILS_VERSION}"
|
||||||
|
|
||||||
cd $BANAN_TOOLCHAIN_DIR
|
|
||||||
|
|
||||||
if [ ! -f ${BINUTILS_VERSION}.tar.xz ]; then
|
if [ ! -f ${BINUTILS_VERSION}.tar.xz ]; then
|
||||||
wget https://ftp.gnu.org/gnu/binutils/${BINUTILS_VERSION}.tar.xz
|
wget https://ftp.gnu.org/gnu/binutils/${BINUTILS_VERSION}.tar.xz
|
||||||
fi
|
fi
|
||||||
|
@ -45,24 +45,26 @@ build_binutils () {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p build/${BINUTILS_VERSION}/
|
mkdir -p build/${BINUTILS_VERSION}/
|
||||||
cd build/${BINUTILS_VERSION}/
|
pushd build/${BINUTILS_VERSION}/
|
||||||
|
|
||||||
../../${BINUTILS_VERSION}/configure \
|
../../${BINUTILS_VERSION}/configure \
|
||||||
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
|
--target="$TARGET" \
|
||||||
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
--prefix="$PREFIX" \
|
||||||
--with-sysroot="$BANAN_SYSROOT" \
|
--with-sysroot="$SYSROOT" \
|
||||||
--disable-nls \
|
--disable-nls \
|
||||||
--disable-werror
|
--disable-werror
|
||||||
|
|
||||||
make -j $(nproc)
|
make -j $(nproc)
|
||||||
make install
|
make install
|
||||||
}
|
|
||||||
|
|
||||||
build_gcc () {
|
popd
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f ${PREFIX}/bin/${TARGET}-g++ ]; then
|
||||||
|
|
||||||
echo "Building ${GCC_VERSION}"
|
echo "Building ${GCC_VERSION}"
|
||||||
|
|
||||||
cd $BANAN_TOOLCHAIN_DIR
|
|
||||||
|
|
||||||
if [ ! -f ${GCC_VERSION}.tar.xz ]; then
|
if [ ! -f ${GCC_VERSION}.tar.xz ]; then
|
||||||
wget https://ftp.gnu.org/gnu/gcc/${GCC_VERSION}/${GCC_VERSION}.tar.xz
|
wget https://ftp.gnu.org/gnu/gcc/${GCC_VERSION}/${GCC_VERSION}.tar.xz
|
||||||
fi
|
fi
|
||||||
|
@ -73,25 +75,27 @@ build_gcc () {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p build/${GCC_VERSION}/
|
mkdir -p build/${GCC_VERSION}/
|
||||||
cd build/${GCC_VERSION}/
|
pushd build/${GCC_VERSION}/
|
||||||
|
|
||||||
../../${GCC_VERSION}/configure \
|
../../${GCC_VERSION}/configure \
|
||||||
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
|
--target="$TARGET" \
|
||||||
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
--prefix="$PREFIX" \
|
||||||
--with-sysroot="$BANAN_SYSROOT" \
|
--with-sysroot="$SYSROOT" \
|
||||||
--disable-nls \
|
--disable-nls \
|
||||||
--enable-languages=c,c++
|
--enable-languages=c,c++
|
||||||
|
|
||||||
make -j $(nproc) all-gcc
|
make -j $(nproc) all-gcc
|
||||||
make -j $(nproc) all-target-libgcc CFLAGS_FOR_TARGET='-g -O2 -mcmodel=large -mno-red-zone'
|
make -j $(nproc) all-target-libgcc CFLAGS_FOR_TARGET='-g -O2 -mcmodel=large -mno-red-zone'
|
||||||
make install-gcc install-target-libgcc
|
make install-gcc install-target-libgcc
|
||||||
}
|
|
||||||
|
|
||||||
build_grub () {
|
popd
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f ${PREFIX}/bin/grub-mkstandalone ]; then
|
||||||
|
|
||||||
echo "Building ${GRUB_VERSION}"
|
echo "Building ${GRUB_VERSION}"
|
||||||
|
|
||||||
cd $BANAN_TOOLCHAIN_DIR
|
|
||||||
|
|
||||||
if [ ! -f ${GRUB_VERSION}.tar.xz ]; then
|
if [ ! -f ${GRUB_VERSION}.tar.xz ]; then
|
||||||
wget https://ftp.gnu.org/gnu/grub/${GRUB_VERSION}.tar.xz
|
wget https://ftp.gnu.org/gnu/grub/${GRUB_VERSION}.tar.xz
|
||||||
fi
|
fi
|
||||||
|
@ -101,29 +105,17 @@ build_grub () {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p build/${GRUB_VERSION}/
|
mkdir -p build/${GRUB_VERSION}/
|
||||||
cd build/${GRUB_VERSION}/
|
pushd build/${GRUB_VERSION}/
|
||||||
|
|
||||||
../../${GRUB_VERSION}/configure \
|
../../${GRUB_VERSION}/configure \
|
||||||
--target="$BANAN_ARCH" \
|
--target="$ARCH" \
|
||||||
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
--prefix="$PREFIX" \
|
||||||
--with-platform="efi" \
|
--with-platform="efi" \
|
||||||
--disable-werror
|
--disable-werror
|
||||||
|
|
||||||
make -j $(nproc)
|
make -j $(nproc)
|
||||||
make install
|
make install
|
||||||
}
|
|
||||||
|
|
||||||
build_libstdcpp () {
|
popd
|
||||||
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
|
fi
|
||||||
|
|
||||||
build_binutils
|
|
||||||
build_gcc
|
|
||||||
build_grub
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
*/
|
|
Loading…
Reference in New Issue