Format OSDK documentation

This commit is contained in:
Jianfeng Jiang
2024-03-01 03:23:47 +00:00
committed by Tate, Hongliang Tian
parent 7fef686136
commit a51b3c7076
18 changed files with 397 additions and 162 deletions

View File

@ -2,16 +2,27 @@
## Overview ## Overview
OSDK (short for Operating System Development Kit) is designed to simplify the development of Rust operating systems. It aims to streamline the process by leveraging [the framekernel architecture](../../kernel/the-framekernel-architecture.md). OSDK (short for Operating System Development Kit)
is designed to simplify the development of Rust operating systems.
It aims to streamline the process
by leveraging [the framekernel architecture](../../kernel/the-framekernel-architecture.md).
OSDK provides a command-line tool `cargo-osdk`, which facilitates project management for those developed on the framekernel architecture. `cargo-osdk` can be used as a subcommand of Cargo. Much like Cargo for Rust projects, `cargo-osdk` enables building, running, and testing projects conveniently. OSDK provides a command-line tool `cargo-osdk`,
which facilitates project management
for those developed on the framekernel architecture.
`cargo-osdk` can be used as a subcommand of Cargo.
Much like Cargo for Rust projects,
`cargo-osdk` enables building, running,
and testing projects conveniently.
## Install OSDK ## Install OSDK
### Requirements ### Requirements
Currently, OSDK only works on x86_64 ubuntu system. We will add support for more operating systems in the future. Currently, OSDK only works on x86_64 ubuntu system.
We will add support for more operating systems in the future.
To run a kernel developed by OSDK with QEMU, the following tools need to be installed: To run a kernel developed by OSDK with QEMU,
the following tools need to be installed:
- Rust >= 1.75.0 - Rust >= 1.75.0
- cargo-binutils - cargo-binutils
- gcc - gcc
@ -20,9 +31,11 @@ To run a kernel developed by OSDK with QEMU, the following tools need to be inst
- ovmf - ovmf
- xorriso - xorriso
About how to install Rust, you can refer to the [official site](https://www.rust-lang.org/tools/install). About how to install Rust, you can refer to
the [official site](https://www.rust-lang.org/tools/install).
`cargo-binutils` can be installed after Rust is installed by `cargo-binutils` can be installed
after Rust is installed by
```bash ```bash
cargo install cargo-binutils cargo install cargo-binutils
``` ```
@ -34,13 +47,15 @@ apt install build-essential grub2-common qemu-system-x86 ovmf xorriso
### Install ### Install
`cargo-osdk` is published on [crates.io](https://crates.io/), and can be installed by `cargo-osdk` is published on [crates.io](https://crates.io/),
and can be installed by
```bash ```bash
cargo install cargo-osdk cargo install cargo-osdk
``` ```
### Upgrate ### Upgrate
If `cargo-osdk` is already installed, the tool can be upgraded by If `cargo-osdk` is already installed,
the tool can be upgraded by
```bash ```bash
cargo install --force cargo-osdk cargo install --force cargo-osdk
``` ```

View File

@ -1,10 +1,16 @@
# Creating an OS Project # Creating an OS Project
OSDK can be used to create a new kernel project or a new library project. A kernel project defines the entry point of the kernel and can be run with QEMU. A library project can provide certain OS functionalities and be imported by other OSes. OSDK can be used to create a new kernel project
or a new library project.
A kernel project defines the entry point of the kernel
and can be run with QEMU.
A library project can provide certain OS functionalities
and be imported by other OSes.
## Creating a new kernel project ## Creating a new kernel project
Creating a new kernel project is simple. You only need to execute the following command: Creating a new kernel project is simple.
You only need to execute the following command:
```bash ```bash
cargo osdk new --kernel myos cargo osdk new --kernel myos
@ -20,11 +26,16 @@ cargo osdk new mylib
## Generated files ## Generated files
Next, we will introduce the contents of the generated project in detail. If you don't wish to delve into the details, you can skip the following sections. Next, we will introduce
the contents of the generated project in detail.
If you don't wish to delve into the details,
you can skip the following sections.
### Overview ### Overview
The generated directory for both the kernel project and library project contains the following contents: The generated directory
for both the kernel project and library project
contains the following contents:
```text ```text
myos/ myos/
@ -39,60 +50,38 @@ myos/
#### Kernel project #### Kernel project
The `src/lib.rs` file contains the code for a simple kernel. The function marked with the `#[aster_main]` macro is considered the kernel entry point by OSDK. The kernel will print `Hello world from the guest kernel!` to the console and then abort. The `src/lib.rs` file contains the code for a simple kernel.
The function marked with the `#[aster_main]` macro
is considered the kernel entry point by OSDK.
The kernel
will print `Hello world from the guest kernel!`to the console
and then abort.
There is also a code snippet that demonstrates how to write kernel mode unit tests. It follows a similar code pattern as user mode unit tests. The test module is marked with the `#[cfg(ktest)]` macro, and each test case is marked with `#[ktest]`. There is also a code snippet that demonstrates
how to write kernel mode unit tests.
It follows a similar code pattern as user mode unit tests.
The test module is marked with the `#[cfg(ktest)]` macro,
and each test case is marked with `#[ktest]`.
```rust ```rust
#![no_std] {{#include ../../../../osdk/src/commands/new/kernel.template}}
#![no_main]
#![forbid(unsafe_code)]
#[macro_use]
extern crate ktest;
use aster_frame::prelude::*;
#[aster_main]
fn kernel_main() -> ! {
println!("Hello world from guest kernel!");
abort();
}
#[cfg(ktest)]
mod tests {
#[ktest]
fn it_works() {
let memory_regions = aster_frame::boot::memory_regions();
assert!(!memory_regions.is_empty());
}
}
``` ```
#### Library project #### Library project
The `src/lib.rs` of library project only contains a simple kernel mode unit test. The `src/lib.rs` of library project only contains
a simple kernel mode unit test.
```rust ```rust
#![no_std] {{#include ../../../../osdk/src/commands/new/lib.template}}
#[macro_use]
extern crate ktest;
extern crate aster_frame;
#[cfg(ktest)]
mod tests {
#[ktest]
fn it_works() {
let memory_regions = aster_frame::boot::memory_regions();
assert!(!memory_regions.is_empty());
}
}
``` ```
### `Cargo.toml` ### `Cargo.toml`
The `Cargo.toml` file is the Rust project manifest. In addition to the contents of a normal Rust project, OSDK will add the dependencies of the Asterinas framework to the file. The dependency version may change over time. The `Cargo.toml` file is the Rust project manifest.
In addition to the contents of a normal Rust project,
OSDK will add the dependencies of the Asterinas framework to the file.
The dependency version may change over time.
```toml ```toml
[dependencies.aster_frame] [dependencies.aster_frame]
@ -106,7 +95,14 @@ branch = "main"
### `OSDK.toml` ### `OSDK.toml`
The `OSDK.toml` file is a manifest that defines the exact behavior of OSDK. By default, it contains the following contents. It includes settings on how to start QEMU to run a kernel. The meaning of each key can be found in the [manifest documentation](../reference/manifest.md). Please avoid changing the default settings unless you know what you are doing. The `OSDK.toml` file is a manifest
that defines the exact behavior of OSDK.
By default, it contains the following contents.
It includes settings on how to start QEMU to run a kernel.
The meaning of each key can be found
in the [manifest documentation](../reference/manifest.md).
Please avoid changing the default settings
unless you know what you are doing.
```toml ```toml
[boot] [boot]
@ -127,4 +123,5 @@ args = [
### `rust-toolchain.toml` ### `rust-toolchain.toml`
The Rust toolchain for the kernel. It aligns with the toolchain of the Asterinas framework. The Rust toolchain for the kernel.
It aligns with the toolchain of the Asterinas framework.

View File

@ -1,8 +1,11 @@
# Testing or Running an OS Project # Testing or Running an OS Project
OSDK allows for convenient building, running, and testing of an OS project. The following example shows the typical workflow. OSDK allows for convenient building, running,
and testing of an OS project.
The following example shows the typical workflow.
Suppose you have created a new kernel project named `myos` and you are in the project directory: Suppose you have created a new kernel project named `myos`
and you are in the project directory:
```bash ```bash
cargo osdk new --kernel myos && cd myos cargo osdk new --kernel myos && cd myos
@ -10,7 +13,8 @@ cargo osdk new --kernel myos && cd myos
## Build the project ## Build the project
To build the project and its dependencies, simply type: To build the project and its dependencies,
simply type:
```bash ```bash
cargo osdk build cargo osdk build
@ -18,15 +22,22 @@ cargo osdk build
## Run the project ## Run the project
To launch the kernel with QEMU, use the following command: To launch the kernel with QEMU,
use the following command:
```bash ```bash
cargo osdk run cargo osdk run
``` ```
OSDK will boot the kernel and initialize OS resources like the console for output, and then hand over control to the kernel entry point to execute the kernel code. OSDK will boot the kernel
and initialize OS resources like the console for output,
and then hand over control to the kernel entry point
to execute the kernel code.
**Note**: Only kernel projects (the projects that defines the function marked with `#[aster_main]`) can be run; library projects cannot. **Note**: Only kernel projects (the projects
that defines the function marked with `#[aster_main]`)
can be run;
library projects cannot.
## Test the project ## Test the project
@ -37,9 +48,11 @@ To run the kernel mode tests, use the following command:
cargo osdk test cargo osdk test
``` ```
OSDK will run all the kernel mode tests in the crate. OSDK will run all the kernel mode tests in the crate.
If you want to run a specific test with a given name, for example, if the test is named `foo`, use the following command: If you want to run a specific test with a given name,
for example, if the test is named `foo`,
use the following command:
```bash ```bash
cargo osdk test foo cargo osdk test foo
@ -47,7 +60,11 @@ cargo osdk test foo
## Options ## Options
Both `build`, `run`, and `test` commands accept options to control their behavior, such as how to compile and launch the kernel. The following documentations provide details on all the available options: Both `build`, `run`, and `test` commands accept options
to control their behavior, such as how to compile and
launch the kernel.
The following documentations provide details on
all the available options:
- [build options](../reference/commands/build.md) - [build options](../reference/commands/build.md)
- [run options](../reference/commands/run.md) - [run options](../reference/commands/run.md)

View File

@ -1,13 +1,86 @@
# Why OSDK # Why OSDK
OSDK is designed to elevate the development experience for Rust OS developers to the ease and convenience typically associated with Rust application development. Imagine crafting operating systems with the same simplicity as applications! This is important to Asterinas as we believe that the project's success is intricately tied to the productivity and happiness of its developers. So OSDK is here to upgrade your dev experience. OSDK is designed to elevate the development experience
for Rust OS developers to the ease and convenience
typically associated with Rust application development.
Imagine crafting operating systems
with the same simplicity as applications!
This is important to Asterinas
as we believe that the project's success
is intricately tied to the productivity and happiness
of its developers.
So OSDK is here to upgrade your dev experience.
To be honest, writing OS kernels is hard. Even when you're using Rust, which is a total game-changer for OS devs, the challenge stands tall. There is a bunch of reasons. To be honest, writing OS kernels is hard.
Even when you're using Rust,
which is a total game-changer for OS devs,
the challenge stands tall.
There is a bunch of reasons.
First, it is hard to write a new kernel from scratch. Everything that has been taken for granted by application developers are gone: no stack, no heap, no threads, not even the standard I/O. It's just you and the no_std world of Rust. You have to implement these basic programming primitives by getting your hands dirty with the most low-level, error-prone, nitty-gritty of computer architecture. It's a journey of learning, doing, and a whole lot of finger-crossing to make sure everything clicks into place. This means a high entry bar for new OS creators. First, it is hard to write a new kernel from scratch.
Everything that has been taken for granted by
application developers are gone:
no stack, no heap, no threads, not even the standard I/O.
It's just you and the no_std world of Rust.
You have to implement these basic programming primitives
by getting your hands dirty with the most low-level,
error-prone, nitty-gritty of computer architecture.
It's a journey of learning, doing, and
a whole lot of finger-crossing
to make sure everything clicks into place.
This means a high entry bar for new OS creators.
Second, it is hard to reuse OS-related libraries/crates across projects. Think about it: most applications share a common groundwork, like libc, Rust's std library, or an SDK. This isn't the case with kernels -- they lack this shared starting point, forcing each one to craft its own set of tools from the ground up. Take device drivers, for example. They often need DMA-capable buffers for chatting with hardware, but since every kernel has its own DMA API flavor, a driver for one kernel is pretty much a no-go for another. This means that for each new kernel out there, developers find themselves having to 'reinvent the wheel' for many core components that are standard in other kernels. Second, it is hard to
reuse OS-related libraries/crates across projects.
Think about it:
most applications share a common groundwork,
like libc, Rust's std library, or an SDK.
This isn't the case with kernels --
they lack this shared starting point,
forcing each one to craft its own set of tools
from the ground up.
Take device drivers, for example.
They often need DMA-capable buffers for chatting with hardware,
but since every kernel has its own DMA API flavor,
a driver for one kernel is pretty much a no-go for another.
This means that for each new kernel out there,
developers find themselves having to 'reinvent the wheel'
for many core components that are standard in other kernels.
Third, it is hard to do unit tests for OS functionalities. Unit testing plays a crucial role in ensuring code quality, but when you're dealing with a monolithic kernel like Linux, it's like a spaghetti bowl of intertwined parts. Trying to isolate one part for testing? Forget about it. You'd have to boot the whole kernel just to test a slice of it. Loadable kernel modules are no exception: you can't test them without plugging them into a live kernel. This monolithic approach to unit testing is slow and unproductive as it performs the job of unit tests at a price of integration tests. Regardless of the kernel architecture, Rust's built-in unit testing facility is not suited for kernel development, leaving each kernel to hack together their own testing frameworks. Third, it is hard to do unit tests for OS functionalities.
Unit testing plays a crucial role in ensuring code quality,
but when you're dealing with a monolithic kernel like Linux,
it's like a spaghetti bowl of intertwined parts.
Trying to isolate one part for testing?
Forget about it.
You'd have to boot the whole kernel just to test a slice of it.
Loadable kernel modules are no exception:
you can't test them without plugging them into a live kernel.
This monolithic approach to unit testing is slow and unproductive
as it performs the job of unit tests
at a price of integration tests.
Regardless of the kernel architecture,
Rust's built-in unit testing facility
is not suited for kernel development,
leaving each kernel to hack together their own testing frameworks.
Last, it is hard to avoid writing unsafe Rust in a Rust kernel. Rust brings safety... well, at least for Rust applications, where you can pretty much stay in the wonderland of safe Rust all the way through. But for a Rust kernel, one cannot help but use unsafe Rust. This is because, among other reasons, low-level operations (e.g., managing page tables, doing context switching, handling interrupts, and interacting with devices) have to be expressed with unsafe Rust features (like executing assembly code or dereferencing raw pointers). The misuse of unsafe Rust could lead to various safety and security issues, as reported by [RustSec Advisory Database](https://rustsec.org). Despite having [a whole book](https://doc.rust-lang.org/nomicon/) to document "the Dark Arts of Unsafe Rust", unsafe Rust is still tricky to use correctly, even among reasoned Rust developers. Last, it is hard to avoid writing unsafe Rust in a Rust kernel.
Rust brings safety...
well, at least for Rust applications,
where you can pretty much stay
in the wonderland of safe Rust all the way through.
But for a Rust kernel,
one cannot help but use unsafe Rust.
This is because, among other reasons,
low-level operations (e.g., managing page tables,
doing context switching, handling interrupts,
and interacting with devices) have to be expressed
with unsafe Rust features (like executing assembly code
or dereferencing raw pointers).
The misuse of unsafe Rust could lead to
various safety and security issues,
as reported by [RustSec Advisory Database](https://rustsec.org).
Despite having [a whole book](https://doc.rust-lang.org/nomicon/)
to document "the Dark Arts of Unsafe Rust",
unsafe Rust is still tricky to use correctly,
even among reasoned Rust developers.

View File

@ -1,6 +1,10 @@
# Working in a Workspace # Working in a Workspace
Typically, an operating system may consist of multiple crates, and these crates may be organized in a workspace. OSDK also supports managing projects in a workspace. Below is an example that demonstrates how to create, build, run, and test projects in a workspace. Typically, an operating system may consist of multiple crates,
and these crates may be organized in a workspace.
OSDK also supports managing projects in a workspace.
Below is an example that demonstrates
how to create, build, run, and test projects in a workspace.
## Creating a new workspace ## Creating a new workspace
@ -45,9 +49,13 @@ myworkspace/
Cargo.toml Cargo.toml
``` ```
In addition to the two projects, OSDK will also generate `OSDK.toml` and `rust-toolchain.toml` at the root of the workspace. In addition to the two projects,
OSDK will also generate `OSDK.toml` and `rust-toolchain.toml`
at the root of the workspace.
Next, add the following function to `mymodule/src/lib.rs`. This function will calculate the available memory after booting: Next, add the following function to `mymodule/src/lib.rs`.
This function will calculate the available memory
after booting:
```rust ```rust
pub fn available_memory() -> usize { pub fn available_memory() -> usize {
@ -63,15 +71,15 @@ Then, add a dependency on `mymodule` to `myos/Cargo.toml`:
mymodule = { path = "../mymodule" } mymodule = { path = "../mymodule" }
``` ```
In `myos/src/lib.rs`, modify the main function as follows. This function will call the function from `mymodule`: In `myos/src/lib.rs`,
modify the main function as follows.
This function will call the function from `mymodule`:
```rust ```rust
#[aster_main] #[aster_main]
fn kernel_main() -> ! { fn kernel_main() {
let avail_mem_as_mb = mymodule::available_memory() / 0x1_000_000; let avail_mem_as_mb = mymodule::available_memory() / 1_000_000;
println!("The available memory is {} MB", avail_mem_as_mb); println!("The available memory is {} MB", avail_mem_as_mb);
abort();
}
``` ```
## Building and Running the kernel ## Building and Running the kernel
@ -83,17 +91,23 @@ cargo osdk build
cargo osdk run cargo osdk run
``` ```
If everything goes well, you will see the output from the guest kernel. If everything goes well,
you will see the output from the guest kernel.
## Running unit test ## Running unit test
You can run test cases from all crates by using the following command in the workspace folder: You can run test cases from all crates
by using the following command in the workspace folder:
```bash ```bash
cargo osdk test cargo osdk test
``` ```
If you want to run test cases from a specific crate, navigate to the crate's folder and run `cargo osdk test`. For example, if you want to test `myos`, use the following command: If you want to run test cases from a specific crate,
navigate to the crate's folder
and run `cargo osdk test`.
For example, if you want to test `myos`,
use the following command:
```bash ```bash
cd myos && cargo osdk test cd myos && cargo osdk test

View File

@ -1,28 +1,46 @@
# OSDK User Reference # OSDK User Reference
OSDK is a command line tool that can be used as a subcommand of Cargo. The common usage of OSDK is: OSDK is a command line tool that can be used
as a subcommand of Cargo.
The common usage of OSDK is:
```bash ```bash
cargo osdk <COMMAND> cargo osdk <COMMAND>
``` ```
You can use `cargo osdk -h` to see the full list of available commands. For the specific usage of a subcommand, you can use `cargo osdk help <COMMAND>`. You can use `cargo osdk -h`
to see the full list of available commands.
For the specific usage of a subcommand,
you can use `cargo osdk help <COMMAND>`.
## Manifest ## Manifest
OSDK utilizes a manifest named `OSDK.toml` to define its precise behavior regarding how to run a kernel with QEMU. The `OSDK.toml` file should be placed in the same folder as the project's `Cargo.toml`. The [Manifest documentation](manifest.md) provides an introduction to all the available configuration options. OSDK utilizes a manifest named `OSDK.toml`
to define its precise behavior regarding
how to run a kernel with QEMU.
The `OSDK.toml` file should be placed
in the same folder as the project's `Cargo.toml`.
The [Manifest documentation](manifest.md)
provides an introduction
to all the available configuration options.
The command line tool can also be used to set the options in the manifest. If both occur, the command line options will always take priority over the options in the manifest. For example, if the manifest defines the path of QEMU as: The command line tool can also be used
to set the options in the manifest.
If both occur, the command line options
will always take priority over the options in the manifest.
For example, if the manifest defines the path of QEMU as:
```toml ```toml
[qemu] [qemu]
path = "/usr/bin/qemu-system-x86_64" path = "/usr/bin/qemu-system-x86_64"
``` ```
But the user provides a new QEMU path when running the project using: But the user provides a new QEMU path
when running the project using:
```bash ```bash
cargo osdk run --qemu.path="/usr/local/qemu-kvm" cargo osdk run --qemu.path="/usr/local/qemu-kvm"
``` ```
Then, the actual path of QEMU should be `/usr/local/qemu-kvm` since command line options have higher priority. Then, the actual path of QEMU should be `/usr/local/qemu-kvm`
since command line options have higher priority.

View File

@ -1,14 +1,18 @@
# Commands # Commands
OSDK provides similar commands as Cargo, and these commands have simalar meanings as corresponding Cargo commands. OSDK provides similar commands as Cargo,
and these commands have simalar meanings
as corresponding Cargo commands.
Currently, OSDK supports the following commands: Currently, OSDK supports the following commands:
- **new**: Create a new kernel package or library package - **new**: Create a new kernel package or library package
- **build**: Compile the project and its dependencies - **build**: Compile the project and its dependencies
- **run**: Run the kernel with a VMM - **run**: Run the kernel with a VMM
- **test**: Execute kernel mode unit test by starting a VMM - **test**: Execute kernel mode unit test by starting a VMM
- **check**: Analyze the current package and report errors - **check**: Analyze the current package and report errors
- **clippy**: Check the current package and catch common mistakes - **clippy**: Check the current package and catch common mistakes
The **new**, **build**, **run** and **test** commands can accept additional options, while the **check** and **clippy** commands cannot. The **new**, **build**, **run** and **test** commands
can accept additional options,
while the **check** and **clippy** commands cannot.

View File

@ -2,44 +2,72 @@
## Overview ## Overview
The `cargo osdk build` command is used to compile the project and its dependencies. The usage is as follows: The `cargo osdk build` command is used to
compile the project and its dependencies.
The usage is as follows:
```bash ```bash
cargo osdk build [OPTIONS] cargo osdk build [OPTIONS]
``` ```
## Options ## Options
The options can be divided into two types: Cargo options that can be accepted by Cargo, and Manifest options that can also be defined in the manifest named `OSDK.toml`. The options can be divided into two types:
Cargo options that can be accepted by Cargo,
and Manifest options that can also be defined
in the manifest named `OSDK.toml`.
### Cargo options ### Cargo options
- `--profile <PROFILE>`: Build artifacts with the specified Cargo profile (built-in candidates are 'dev', 'release', 'test', and 'bench') [default: dev] - `--profile <PROFILE>`:
- `--release`: Build artifacts in release mode, with optimizations Build artifacts with the specified Cargo profile
- `--features <FEATURES>`: Space or comma separated list of features to activate (built-in candidates are 'dev', 'release', 'test', and 'bench')
[default: dev]
- `--release`:
Build artifacts in release mode, with optimizations
- `--features <FEATURES>`:
Space or comma separated list of features to activate
### Manifest options ### Manifest options
These options can also be defined in the project's manifest named `OSDK.toml`. Command line options are used to override or append values in `OSDK.toml`. The allowed values for each option can be found in the [Manifest Documentation](../manifest.md). These options can also be defined
in the project's manifest named `OSDK.toml`.
Command line options are used to override
or append values in `OSDK.toml`.
The allowed values for each option can be found
in the [Manifest Documentation](../manifest.md).
- `--kcmd_args <ARGS>`: Command line arguments for the guest kernel - `--kcmd_args <ARGS>`:
- `--init_args <ARGS>`: Command line arguments for the init process Command line arguments for the guest kernel
- `--initramfs <PATH>`: Path of the initramfs - `--init_args <ARGS>`:
- `--boot.ovmf <PATH>`: Path of the OVMF directory Command line arguments for the init process
- `--boot.loader <LOADER>`: Loader for booting the kernel - `--initramfs <PATH>`:
- `--boot.protocol <PROTOCOL>`: Protocol for booting the kernel Path of the initramfs
- `--qemu.path <PATH>`: Path of QEMU - `--boot.ovmf <PATH>`:
- `--qemu.machine <MACHINE>`: QEMU machine type Path of the OVMF directory
- `--qemu.args <ARGS>`: Arguments for running QEMU - `--boot.loader <LOADER>`:
Loader for booting the kernel
- `--boot.protocol <PROTOCOL>`:
Protocol for booting the kernel
- `--qemu.path <PATH>`:
Path of QEMU
- `--qemu.machine <MACHINE>`:
QEMU machine type
- `--qemu.args <ARGS>`:
Arguments for running QEMU
## Examples ## Examples
- Build a project with `./initramfs.cpio.gz` as the initramfs and `multiboot2` as the boot portocol: - Build a project with `./initramfs.cpio.gz`
as the initramfs and `multiboot2` as the boot portocol:
```bash ```bash
cargo osdk build --initramfs="./initramfs.cpio.gz" --boot.protocol="multiboot2" cargo osdk build --initramfs="./initramfs.cpio.gz" --boot.protocol="multiboot2"
``` ```
- Build a project and append `sh`, `-l` to init process arguments: - Build a project and append `sh`, `-l`
to init process arguments:
```bash ```bash
cargo osdk build --init_args="sh" --init_args="-l" cargo osdk build --init_args="sh" --init_args="-l"

View File

@ -2,7 +2,10 @@
## Overview ## Overview
The `cargo osdk new` command is used to create a kernel project or a new library project. The usage is as follows: The `cargo osdk new` command
is used to create a kernel project
or a new library project.
The usage is as follows:
```bash ```bash
cargo osdk new [OPTIONS] <name> cargo osdk new [OPTIONS] <name>
@ -10,11 +13,14 @@ cargo osdk new [OPTIONS] <name>
## Arguments ## Arguments
`<name>`: the name of the crate. `<name>`: the name of the crate.
## Options ## Options
`--kernel`: Use the kernel template. If this option is not set, the library template will be used by default. `--kernel`:
Use the kernel template.
If this option is not set,
the library template will be used by default.
## Examples ## Examples
@ -24,7 +30,7 @@ cargo osdk new [OPTIONS] <name>
cargo osdk new --kernel myos cargo osdk new --kernel myos
``` ```
- Create a new library named `mymodule`: - Create a new library named `mymodule`:
```bash ```bash
cargo osdk new mymodule cargo osdk new mymodule

View File

@ -2,7 +2,8 @@
## Overview ## Overview
`cargo osdk run` is used to run the kernel with QEMU. The usage is as follows: `cargo osdk run` is used to run the kernel with QEMU.
The usage is as follows:
```bash ```bash
cargo osdk run [OPTIONS] cargo osdk run [OPTIONS]
@ -10,4 +11,6 @@ cargo osdk run [OPTIONS]
## Options ## Options
The options are the same as those of `cargo osdk build`. Refer to the [documentation](build.md) of `cargo osdk build` for more details. The options are the same as those of `cargo osdk build`.
Refer to the [documentation](build.md) of `cargo osdk build`
for more details.

View File

@ -1,6 +1,8 @@
# cargo osdk test # cargo osdk test
`cargo osdk test` is used to execute kernel mode unit test by starting QEMU. The usage is as follows: `cargo osdk test` is used to
execute kernel mode unit test by starting QEMU.
The usage is as follows:
```bash ```bash
cargo osdk test [OPTIONS] [TESTNAME] cargo osdk test [OPTIONS] [TESTNAME]
@ -8,14 +10,18 @@ cargo osdk test [OPTIONS] [TESTNAME]
## Arguments ## Arguments
[TESTNAME]: Only run tests containing this string in their names [TESTNAME]:
Only run tests containing this string in their names
## Options ## Options
The options are the same as those of `cargo osdk build`. Refer to the [documentation](build.md) of `cargo osdk build` for more details. The options are the same as those of `cargo osdk build`.
Refer to the [documentation](build.md) of `cargo osdk build`
for more details.
## Examples ## Examples
- Execute tests containing foo in their names with q35 as the QEMU machine type: - Execute tests containing foo in their names
with q35 as the QEMU machine type:
```bash ```bash
cargo osdk test foo --qemu.machine="q35" cargo osdk test foo --qemu.machine="q35"

View File

@ -2,17 +2,34 @@
## Overview ## Overview
OSDK utilizes a manifest to define its precise behavior. Typically, the configuration file is named `OSDK.toml` and is placed in the root directory of the workspace (the same directory as the workspace's `Cargo.toml`). If there is only one crate and no workspace, the file is placed in the crate's root directory. OSDK utilizes a manifest to define its precise behavior.
Typically, the configuration file is named `OSDK.toml`
and is placed in the root directory of the workspace
(the same directory as the workspace's `Cargo.toml`).
If there is only one crate and no workspace,
the file is placed in the crate's root directory.
For a crate inside workspace, it may have two related manifests, one is of the workspace (the `OSDK.toml` in the same directory as the workspace's `Cargo.toml`) and one of the crate (in the same directory as the crate's `Cargo.toml`). So which manifest should be used? The rules are For a crate inside workspace,
- If running commands in the workspace root directory, the `OSDK.toml` of the workspace will be used it may have two related manifests,
one is of the workspace
(in the same directory as the workspace's `Cargo.toml`)
and one of the crate
(in the same directory as the crate's `Cargo.toml`).
So which manifest should be used?
The rules are
- If running commands in the workspace root directory,
the `OSDK.toml` of the workspace will be used
- If running commands in the crate directory - If running commands in the crate directory
- If the crate has `OSDK.toml`, the `OSDK.toml` of the crate will be used. - If the crate has `OSDK.toml`,
the `OSDK.toml` of the crate will be used.
- Otherwise, `the OSDK.toml` of the workspace will be used. - Otherwise, `the OSDK.toml` of the workspace will be used.
## Configurations ## Configurations
Below, you will find a comprehensive version of the available configuration options in the manifest. Below, you will find a comprehensive version of
the available configuration options in the manifest.
```toml ```toml
kcmd_args = ["init=/bin/busybox", "path=/usr/local/bin"] # <1> kcmd_args = ["init=/bin/busybox", "path=/usr/local/bin"] # <1>
@ -35,30 +52,74 @@ args = [ # <10>
] ]
``` ```
1. The arguments provided will be passed to the guest kernel. 1. The arguments provided will be passed to the guest kernel.
Optional. The default value is empty.
Each argument should be in one of the following two forms: `KEY=VALUE` or `KEY` if no value is required. Each `KEY` can appear at most once.
2. The arguments provided will be passed to the init process, usually, the init shell.
Optional. The default value is empty. Optional. The default value is empty.
3. The path to the built initramfs.
Each argument should be in one of the following two forms:
`KEY=VALUE` or `KEY` if no value is required.
Each `KEY` can appear at most once.
2. The arguments provided will be passed to the init process,
usually, the init shell.
Optional. The default value is empty. Optional. The default value is empty.
4. The bootloader used to boot the kernel.
Optional. The default value is `grub`. 3. The path to the built initramfs.
The allowed values are `grub` and `qemu` (`qemu` indicates that QEMU directly boots the kernel).
5. The boot protocol used to boot the kernel. Optional. The default value is empty.
Optional. The default value is `multiboot2`.
The allowed values are `linux-efi-handover64`, `linux-legacy32`, `multiboot`, and `multiboot2`. 4. The bootloader used to boot the kernel.
6. The path of `grub-mkrescue`, which is used to create a GRUB CD_ROM.
Optional. The default value is system path, determined using `which grub-mkrescue`. Optional. The default value is `grub`.
This argument only takes effect when the bootloader is `grub`.
7. The path of OVMF. OVMF enables UEFI support for QEMU. The allowed values are `grub` and `qemu`
Optional. The default value is empty. (`qemu` indicates that QEMU directly boots the kernel).
This argument only takes effect when the boot protocol is `linux-efi-handover64`.
8. The path of QEMU. 5. The boot protocol used to boot the kernel.
Optional. The default value is system path, determined using `which qemu-system-x86_64`.
9. The machine type of QEMU. Optional. The default value is `multiboot2`.
Optional. Default is `q35`.
The allowed values are `q35` and `microvm`. The allowed values are `linux-efi-handover64`,
10. Additional arguments passed to QEMU. `linux-legacy32`, `multiboot`, and `multiboot2`.
Optional. The default value is empty.
Each argument should be in the form `KEY VALUE` (separated by space), or `KEY` if no value is required. Some keys can appear multiple times (e.g., `-device`, `-netdev`), while other keys can appear at most once. Certain keys, such as `-cpu` and `-machine`, are not allowed to be set here as they may conflict with the internal settings of OSDK. 6. The path of `grub-mkrescue`,
which is used to create a GRUB CD_ROM.
Optional. The default value is system path,
determined using `which grub-mkrescue`.
This argument only takes effect
when the bootloader is `grub`.
7. The path of OVMF. OVMF enables UEFI support for QEMU.
Optional. The default value is empty.
This argument only takes effect
when the boot protocol is `linux-efi-handover64`.
8. The path of QEMU.
Optional. The default value is system path,
determined using `which qemu-system-x86_64`.
9. The machine type of QEMU.
Optional. Default is `q35`.
The allowed values are `q35` and `microvm`.
10. Additional arguments passed to QEMU.
Optional. The default value is empty.
Each argument should be in the form `KEY VALUE`
(separated by space),
or `KEY` if no value is required.
Some keys can appear multiple times
(e.g., `-device`, `-netdev`),
while other keys can appear at most once.
Certain keys, such as `-cpu` and `-machine`,
are not allowed to be set here
as they may conflict with the internal settings of OSDK.

View File

@ -46,7 +46,8 @@ pub fn panic_handler(info: &core::panic::PanicInfo) -> ! {
abort(); abort();
} }
fn abort() -> ! { // Aborts the QEMU
pub fn abort() -> ! {
exit_qemu(QemuExitCode::Failed); exit_qemu(QemuExitCode::Failed);
} }

View File

@ -11,5 +11,6 @@ pub use aster_main::aster_main;
pub use crate::{ pub use crate::{
early_print as print, early_println as println, early_print as print, early_println as println,
panicking::abort,
vm::{Paddr, Vaddr}, vm::{Paddr, Vaddr},
}; };

View File

@ -14,6 +14,7 @@ pub fn aster_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
pub fn __aster_main() -> ! { pub fn __aster_main() -> ! {
aster_frame::init(); aster_frame::init();
#main_fn_name(); #main_fn_name();
aster_frame::prelude::abort();
} }
#main_fn #main_fn

View File

@ -8,7 +8,7 @@ extern crate aster_frame;
use aster_frame::prelude::*; use aster_frame::prelude::*;
#[aster_main] #[aster_main]
pub fn main() -> ! { pub fn main() {
println!("[kernel] finish init aster_frame"); println!("[kernel] finish init aster_frame");
component::init_all(component::parse_metadata!()).unwrap(); component::init_all(component::parse_metadata!()).unwrap();
aster_nix::init(); aster_nix::init();

View File

@ -1,5 +1,4 @@
#![no_std] #![no_std]
#![no_main]
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
#[macro_use] #[macro_use]
@ -8,16 +7,6 @@ extern crate ktest;
use aster_frame::prelude::*; use aster_frame::prelude::*;
#[aster_main] #[aster_main]
fn kernel_main() -> ! { fn kernel_main() {
println!("Hello world from guest kernel!"); println!("Hello world from guest kernel!");
loop {}
}
#[cfg(ktest)]
mod tests {
#[ktest]
fn it_works() {
let memory_regions = aster_frame::boot::memory_regions();
assert!(!memory_regions.is_empty());
}
} }

View File

@ -1,4 +1,5 @@
#![no_std] #![no_std]
#![forbid(unsafe_code)]
#[macro_use] #[macro_use]
extern crate ktest; extern crate ktest;