# Developer Resources

## Design Goals & Philosophy

General design goals are outlined in [DESIGN.md](DESIGN.md). Security-relevant
design details can be found in [SECURITY.md](SECURITY.md).

## Navigating

- [src/kernel/](../src/kernel/): Kernel-specific code.
  - [arch/](../src/kernel/arch/): Architecture specific features like the
  display, serial, and interrupts. Each architecture is a subfolder,
  containing a file or module for each feature.
  - [boot/](../src/kernel/boot/mod.rs): Handles bootloader-managed data
  structures. Gila uses Limine. Other bootloaders are NOT supported.
    - [params.rs](../src/kernel/boot/params.rs): Command line parameter parsing.
    - [modules.rs](../src/kernel/boot/modules.rs): Kernel module handling.
  - [constants.rs](../src/kernel/constants.rs): Constants referenced elsewhere
  in the kernel.
  - [log.rs](../src/kernel/log.rs): Logging structures, macros, and singletons
  for logging to serial or the display.
  - [interrupt/](../src/kernel/interrupt/mod.rs): Interrupt handlers with
  platform-agnostic APIs.
  - [main.rs](../src/kernel/main.rs): The entry point that gets called by the
  bootloader.
  - [memory.rs](../src/kernel/memory.rs): Types relating to memory regions and
  allocation.
  - [panic.rs](../src/kernel/panic.rs): The panic handler and associated
  functionality.
  - [process.rs](../src/kernel/process.rs): Process types and functions.
  - [syscall\_runner.rs](../src/kernel/syscall_runner.rs): Chooses a system call
  by its ID and defers actual syscall execution to code in `/src/lib/`.
- [src/userboot/](../src/userboot/): The first Ring 3 binary to run.
- [src/linker_scripts](../src/linker_scripts/): Linker scripts for binaries.
- [src/lib/](../src/lib/lib.rs): Shared between the kernel and any
  binaries built for it. Contains any definitions, structures, and types that will
  cross the boundary between userspace and kernelspace, including those sent over IPC.
  - [arch/](../src/lib/arch/mod.rs): Architecture specific functionality like
  system call register storing/loading.
  - [syscall.rs](../src/lib/syscall.rs): System call types common to apps and
  the kernel.

## Building and running

Building a bootable kernel is easy. All you need to do is run
`cargo build --bin kernel`, and a valid, bootable Limine executable will be
generated. However, it cannot be booted without installing it in a bootable
Limine filesystem, and it cannot do anything useful without an initramfs
containing system servers, such as the init server and device drivers.

> [!NOTE]
> The ISO build system will be removed once Gila reaches a stable version,
> and instead, bootable image creation will be handled by the system software
> distribution.

This project uses [cargo-make](https://github.com/sagiegurari/cargo-make) to
handle building ISOs and managing files not associated with Cargo. You need to
install it before you can build an ISO automatically. To do so, you can run
`cargo install cargo-make`. 

### Dependencies

If you use NixOS or the Nix package manager, simply run `nix-shell` in the root
directory. All necessary dependencies will be made available.

If not, the following dependencies will need to be manually installed:

- `rustup` command installed
- `limine` command installed
- `xorriso` command installed
- `qemu-system-{your target architecture}` command installed (for running)

### Build System

Run `cargo make` to invoke the [Makefile.toml](../Makefile.toml).

- `cargo make clean_all`: Cleans all built binaries, libraries, and ISO build files.
- `cargo make clean_iso`: Cleans the ISO build directory.
- `cargo make lib`: Builds `libgila`, the library that the kernel and user
code are linked against.
- `cargo make kernel`: Builds the kernel ELF file.
- `cargo make userboot`: Build the userspace init binary.
- `cargo make iso`: Builds the bootable ISO with Limine installed.
- `cargo make run`: Builds the ISO and boots it in QEMU.
- `cargo make gui_run`: Same as above, but with QEMU in GUI mode.
- `cargo make debug`: Launch the kernel in QEMU with debugging enabled, and
start and connect GDB.

You do not need to clean any files after making changes. The `lib`, `kernel`, `userboot`,
and `iso` tasks will automatically be rerun if their input files change.

### Configuration

- Variable `LIMINEDIR`: Location of binary files for limine. Default is
`/usr/share/limine`.
- Variable `TARGET`: rustc target triple to compile for. Default is
`x86_64-unknown-none`. Options are listed [in the targets section](#targets).
- Argument `-p`: Rust build profile to use. Default is `dev`. Options are
`dev` and `release`.

> [!NOTE]
> The `-p {profile}` argument must go between `cargo make` and the task
> argument.

### Targets

Gila ~~currently supports~~ aims to support four different CPU architectures:

- `x86_64`
- `aarch64`
- `riscv64`
- `loongarch64`

It currently only builds on `x86_64`, and will continue to only support it
until I can implement support for important features in other architectures.

All these architectures are supported by Limine, and the appropriate backends
are present in the Makefile to compile and build bootable images for each.
While Limine (the bootloader) and rustc also support `IA32` (also referred to
as `i686`), the Limine boot protocol cannot work on a 32-bit architecture, as
it relies heavily on 64-bit pointers. Compilation will fail if a build for an
unsupported target is attempted.

EFI boot is presently supported, at least on `x86_64`. No features depend on
EFI, and as such, the `uefi` feature can be safely disabled when booting
through BIOS.

## Kernel Parameters

Kernel parameters are passed as part of the `cmdline` through
[limine.conf](../configs/limine.conf). The parameters are passed as a
space-delimited list of keys and values. Keys begin with a hyphen (`-`), and
keys are separated from their values with equals signs (`=`). Keys can have a
set of multiple values, separated by a comma (`,`). Gila does not currently
support parameter values with spaces. That would require an *actual* parser.

List of current extant kernel parameters:

- `-loglevel`: Can be a number or string corresponding to a log level. Only
one value supported. Current options are `Disabled`, `Trace`, `Info`,
`Warning`, `Error`, and `Critical`. This parameter is case insensitive.
- `-logdev`: A sequence of one or more values representing devices to log to.
Current options are `display` and `serial`. This parameter is case
insensitive.

The default behavior for each parameter, when not supplied, is:

`-loglevel=Info`

## Writing Programs for Gila

Gila's system calls will soon be fully defined in `libgila`. The library is
developed in tandem with, and is used within, the kernel. As such, it is
treated as part of the kernel. Programs built against the wrong version of
`libgila` will not work due to mismatched definitions.

As Gila is merely a kernel, and its userspace will heavily depend on whatever
servers and drivers are included alongside it, no standard library for any
language will ever be issued as part of the kernel's software package. Instead,
this will be deferred to the system software developer who designs and
integrates the userspace.

To compile software for Gila, simply write your program as if it were a `no_std`
binary for the kernel's processor architecture. By linking against `libgila`,
the program may access things like system calls, error types, and IPC data formats.

## Contributing

Contribution policies are outlined in [CONTRIBUTING.md](CONTRIBUTING.md).
