Devicetree drivers are created by using the `DEVICETREE_DRIVER` macro.
That macro creates a new class deriving from `DeviceTree::Driver` and
inserts it into the driver init section.
The driver code then has to implement the `probe` member function, which
will be called if `DeviceTree::Management` finds a node with a
compatible property entry that was in the array passed as the second
argument to the `DEVICETREE_DRIVER` macro.
The `probe` function then will check if it supports the given node and
if so, registers a `DeviceTree::DeviceRecipe` at the appropriate
subsystem, which will then create a device from that recipe once it is
initialized.
The driver can store the necessary info it got from the devicetree,
such as the physical address and interrupt numbers, in the capture
list of the callback lambda stored in `DeviceRecipe::create_device`.
The `DeviceTree::DeviceRecipe`s are necessary, as the `probe` functions
might not be able to create an instance of the actual device class,
since doing so can depend on some subsystems being initialized first.
This commit reorganizes the BootInfo struct definition so it can be
shared for all architectures.
The existing free extern "C" boot info variables have been removed and
replaced with a global BootInfo struct, 'g_boot_info'.
On x86-64, the BootInfo is directly copied from the Prekernel-provided
struct.
On AArch64 and RISC-V, BootInfo is populated during pre_init.
This change has many improvements:
- We don't use `LockRefPtr` to hold instances of many base devices as
with the DeviceManagement class. Instead, we have a saner pattern of
holding them in a `NonnullRefPtr<T> const`, in a small-text footprint
class definition in the `Device.cpp` file.
- The awkwardness of using `::the()` each time we need to get references
to mostly-static objects (like the Event queue) in runtime is now gone
in the migration to using the `Device` class.
- Acquiring a device feel more obvious because we use now the Device
class for this method. The method name is improved as well.
Plain old VGA text mode functionality was introduced in 1987, and is
obviously still used on some (even modern) x86 machines.
However, it's very limited in what it gives to us, because by using a
80x25 text mode console, it's guaranteed that no desktop functionality
is available during such OS runtime session.
It's also quite complicated to handle access arbitration on the VGA ISA
ports which means that only one VGA card can work in VGA mode, which
makes it very cumbersome to manage multiple cards at once.
Since we never relied on the VGA text mode console for anything serious,
as booting on a QEMU machine always gives a proper framebuffer to work
with, VGA text mode console was used in bare metal sessions due to lack
of drivers.
However, since we "force" multiboot-compatible bootloaders to provide us
a framebuffer, it's basically a non-issue to have a functional console
on bare metal machines even if we don't have the required drivers.
Similarly to VFSRootContext and ScopedProcessList, this class intends
to form resource isolation as well.
We add this class as an infrastructure preparation of hostname contexts
which should allow processes to obtain different hostnames on the same
machine.
There's no point in constructing an object just for the sake of keeping
a state that can be touched by anything in the kernel code.
Let's reduce everything to be in a C++ namespace called with the
previous name "VirtualFileSystem" and keep a smaller textual-footprint
struct called "VirtualFileSystemDetails".
This change also cleans up old "friend class" statements that were no
longer needed, and move methods from the VirtualFileSystem code to more
appropriate places as well.
Please note that the method of locking all filesystems during shutdown
is removed, as in that place there's no meaning to actually locking all
filesystems because of running in kernel mode entirely.
The VFSRootContext class, as its name suggests, holds a context for a
root directory with its mount table and the root custody/inode in the
same class.
The idea is derived from the Linux mount namespace mechanism.
It mimicks the concept of the ProcessList object, but it is adjusted for
a root directory tree context.
In contrast to the ProcessList concept, processes that share the default
VFSRootContext can't see other VFSRootContext related properties such as
as the mount table and root custody/inode.
To accommodate to this change progressively, we internally create 2 main
VFS root contexts for now - one for kernel processes (as they don't need
to care about VFS root contexts for the most part), and another for all
userspace programs.
This separation allows us to continue pretending for userspace that
everything is "normal" as it is used to be, until we introduce proper
interfaces in the mount-related syscalls as well as in the SysFS.
We make VFSRootContext objects being listed, as another preparation
before we could expose interfaces to userspace.
As a result, the PowerStateSwitchTask now iterates on all contexts
and tear them down one by one.
We don't really need it, and the entire functionality can be organically
intergrated into the VirtualConsole class, to switch between the Virtual
consoles, and manage initialization of all consoles in the global array.
The new baked image is a Prekernel and a Kernel baked together now, so
essentially we no longer need to pass the Prekernel as -kernel and the
actual kernel image as -initrd to QEMU, leaving the option to pass an
actual initrd or initramfs module later on with multiboot.
Nobody uses this functionality. I used this code on my old 2007 ICH7
test machine about a year ago, but bare metal is a small aspect of the
project, so it's safe to assume that nobody really tests this piece of
code.
Therefore, let's drop this for good and focus on more modern hardware.
We have many places in the kernel code that we have boolean flags that
are only set once, and never reset again but are checked multiple times
before and after the time they're being set, which matches the purpose
of the SetOnce class.
Sticking this to the function source has multiple benefits:
- We instrument more code, by not excluding entire files.
- NO_SANITIZE_COVERAGE can be used in Header files.
- Keeping the info with the source code, means if a function or
file is moved around, the NO_SANITIZE_COVERAGE moves with it.
This simple delay loop uses the time CSR to wait for the given amount
of time. The tick frequency of the CSR is read from the
/cpus/timebase-frequency devicetree property.
Other arches don't use the prekernel, so don't try to unmap it on
non-x86 platforms.
For some reason, this didn't cause aarch64 to crash, but on riscv64 this
would cause a panic.
There's no need to have separate syscall for this kind of functionality,
as we can just have a device node in /dev, called "beep", that allows
writing tone generation packets to emulate the same behavior.
In addition to that, we remove LibC sysbeep function, as this function
was never being used by any C program nor it was standardized in any
way.
Instead, we move the userspace implementation to LibCore.
Moving the DeviceManagement initialization, which is only needed by
userland in the first place, to after interrupt and time management
initialization (like other things that require randomness) allows the
SipHash initialization to access good randomness without problems.
Note: There currently is another, unrelated boot problem on aarch64,
which is not caused by SipHash as far as we know. This commit therefore
only fixes the SipHash regression.
According to multiboot spec if flag for framebuffer isn't
set then corresponding fields are invalid. In reality they're set
to 0 but let's be defensive.
The VirtIO specification defines many types of devices with different
purposes, and it also defines 3 possible transport mediums where devices
could be connected to the host machine.
We only care about the PCIe transport, but this commit puts the actual
foundations for supporting the lean MMIO transport too in the future.
To ensure things are kept abstracted but still functional, the VirtIO
transport code is responsible for what is deemed as related to an actual
transport type - allocation of interrupt handlers and tinkering with low
level transport-related registers, etc.
Instead, use the FixedCharBuffer class to ensure we always use a static
buffer storage for these names. This ensures that if a Process or a
Thread were created, there's a guarantee that setting a new name will
never fail, as only copying of strings should be done to that static
storage.
The limits which are set are 32 characters for processes' names and 64
characters for thread names - this is because threads' names could be
more verbose than processes' names.
Instead of having a single available memory range that encompasses the
whole 0x00000000-0x3EFFFFFF range of physical memory, create a separate
reserved entry for the RAM range used by the VideoCore. This fixes a
crash that happens when we try to allocate physical pages in the GPU's
reserved range.
This will eventually be replaced with parsing the data from the device
tree, but for now, this should solve some of the recurring CI failures.
Like the HID, Audio and Storage subsystem, the Graphics subsystem (which
handles GPUs technically) exposes unix device files (typically in /dev).
To ensure consistency across the repository, move all related files to a
new directory under Kernel/Devices called "GPU".
Also remove the redundant "GPU" word from the VirtIO driver directory,
and the word "Graphics" from GraphicsManagement.{h,cpp} filenames.
This has KString, KBuffer, DoubleBuffer, KBufferBuilder, IOWindow,
UserOrKernelBuffer and ScopedCritical classes being moved to the
Kernel/Library subdirectory.
Also, move the panic and assertions handling code to that directory.
The Storage subsystem, like the Audio and HID subsystems, exposes Unix
device files (for example, in the /dev directory). To ensure consistency
across the repository, we should make the Storage subsystem to reside in
the Kernel/Devices directory like the two other mentioned subsystems.
While the PL011-based UART0 is currently reserved for the kernel
console, UART1 is free to be exposed to the userspace as `/dev/ttyS0`.
This will be used as the stdout of `run-tests-and-shutdown.sh` when
testing the AArch64 kernel.
This logo was actually used as a first sign of life in the very early
days of the aarch64 port.
Now that we boot into the graphical mode of the system just fine there's
no need to keep this.
Since multiboot_modules_count is set to 0, we can safely set the
multiboot_modules pointer to 0 (null pointer), as we don't use multiboot
on aarch64 anyway.