Skip to content

Commit

Permalink
feat: add fs-img support
Browse files Browse the repository at this point in the history
  • Loading branch information
yfblock committed Nov 16, 2024
1 parent 1eed1fa commit ba0d31c
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 69 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[patch."https://github.com/Byte-OS/fs.git".fs]
path = "crates/fs"

[profile.release]
debug = true

Expand Down
2 changes: 2 additions & 0 deletions byteos
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { Command } from "https://deno.land/x/[email protected]/command/mod.ts";
import { cliCommand as buildCommand } from './scripts/cli-build.ts';
import { cliCommand as qemuCommand } from './scripts/cli-qemu.ts';
import { cliCommand as rootfsCommand } from './scripts/cli-rootfs.ts';
import { logLevelEnum, archEnum } from './scripts/cli-types.ts';
import { parse } from "jsr:@std/yaml";

Expand All @@ -18,6 +19,7 @@ const command = new Command()

// Sub Command build
.command("build", buildCommand)
.command("rootfs", rootfsCommand)
.command("qemu", qemuCommand);

// parse yaml file
Expand Down
2 changes: 1 addition & 1 deletion scripts/cli-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { KernelBuilder } from "./kernel.ts";

export const cargoBuild = async function(options: CommandOptions<globalArgType>) {

const builder = new KernelBuilder(options.arch);
const builder = new KernelBuilder(options.arch, options.logLevel);
await builder.buildElf();
await builder.convertBin();

Expand Down
83 changes: 33 additions & 50 deletions scripts/cli-qemu.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Command, CommandOptions } from "https://deno.land/x/[email protected]/command/mod.ts";
import { globalArgType } from "./cli-types.ts";
import { KernelBuilder } from "./kernel.ts";
import { runCommand } from "./runHelper.ts";
import { parseArgsString } from "./runHelper.ts";

class QemuRunner {
arch: string;
Expand All @@ -9,72 +11,53 @@ class QemuRunner {
memorySize: string = "1G";
smp: string = "1";


constructor(options: CommandOptions<globalArgType>, builder: KernelBuilder) {
this.arch = options.arch;
this.builder = builder;
if(this.arch == "x86_64" || this.arch == "loongarch64")
if (this.arch == "x86_64" || this.arch == "loongarch64")
this.bus = "pci";
}

getQemuArchExec(): string[] {
return {
x86_64: [
"-machine",
"q35",
"-kernel",
this.builder.elfPath,
"-cpu",
"IvyBridge-v2"
],
riscv64: [
"-machine",
"virt",
"-kernel",
this.builder.binPath
],
aarch64: [
"-cpu",
"cortex-a72",
"-machine",
"virt",
"-kernel",
this.builder.binPath
],
loongarch64: [
"-kernel",
this.builder.elfPath
]
x86_64: parseArgsString(`
-machine q35
-kernel ${this.builder.elfPath}
-cpu IvyBridge-v2
`),
riscv64: parseArgsString(`
-machine virt
-kernel ${this.builder.binPath}
`),
aarch64: parseArgsString(`
-machine virt
-cpu cortex-a72
-kernel ${this.builder.binPath}
`),
loongarch64: parseArgsString(`
-kernel ${this.builder.elfPath}
`)
}[this.arch] ?? [];
}

async run() {
const qemuCommand = new Deno.Command(`qemu-system-${this.arch}`, {
args: [
...this.getQemuArchExec(),
"-m",
this.memorySize,
"-nographic",
"-smp",
this.smp,
// Dump Debug information.
"-D",
"qemu.log",
"-d",
"in_asm,int,pcall,cpu_reset,guest_errors",
// Add virtio block device.
"-drive",
"file=mount.img,if=none,format=raw,id=x0",
"-device",
"virtio-blk-device,drive=x0"
]
});
await qemuCommand.spawn().status;
await runCommand(`
qemu-system-${this.arch} ${this.getQemuArchExec().join(" ")}
-m ${this.memorySize}
-smp ${this.smp}
-D qemu.log",
-d in_asm,int,pcall,cpu_reset,guest_errors
-drive
file=mount.img,if=none,format=raw,id=x0
-device
virtio-blk-${this.bus},drive=x0
-nographic
`).spawn().status;
}
}

async function runQemu(options: CommandOptions<globalArgType>) {
const builder = new KernelBuilder(options.arch);
const builder = new KernelBuilder(options.arch, options.logLevel);
await builder.buildElf();
await builder.convertBin();

Expand Down
35 changes: 35 additions & 0 deletions scripts/cli-rootfs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Command, CommandOptions } from "https://deno.land/x/[email protected]/command/mod.ts";
import { globalArgType } from "./cli-types.ts";
import { runCommand } from "./runHelper.ts";

/**
* Build the root filesystem image for the kernel.
* @param options Global arguments for the command.
*/
async function buildRootFS(options: CommandOptions<globalArgType>) {
// Create disk image
const ddStatus = await runCommand(`
dd if=/dev/zero of=mount.img bs=1M count=64
`).spawn().status;
if (!ddStatus.success) return;

// Format the disk image as ext4
const mkfsStatus = await runCommand(`
mkfs.ext4 -F -O ^metadata_csum_seed mount.img
`).spawn().status;
if (!mkfsStatus.success) return;

// Mount the disk image to a temporary directory
// and copy the necessary files into it
if(!(await Deno.lstat("mount")).isDirectory) {
await Deno.mkdir("mount");
};

await runCommand(`sudo mount mount.img mount`).spawn().status;
await runCommand(`sudo rsync -r tools/testcase-${options.arch}/ mount`).spawn().status;
await runCommand(`sudo umount mount`).spawn().status;
}

export const cliCommand = new Command<globalArgType>()
.description("Build root fs image for the kernel")
.action(buildRootFS);
37 changes: 22 additions & 15 deletions scripts/kernel.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { runCommand } from "./runHelper.ts";

const targetMap: Record<string, string> = {
"riscv64": 'riscv64gc-unknown-none-elf',
"x86_64": 'x86_64-unknown-none',
Expand All @@ -10,13 +12,19 @@ export class KernelBuilder {
elfPath: string;
binPath: string;
rustflags: string;
extraArgs: string[] = [];
logLvl: string;

constructor(arch: string) {
constructor(arch: string, logLvl: string) {
this.arch = arch;
this.elfPath = `${Deno.cwd()}/target/${targetMap[arch]}/release/kernel`;
this.binPath = `${this.elfPath}.bin`;

this.rustflags = Deno.env.get('RUSTFLAGS') || "";
this.logLvl = logLvl;

if(arch == "loongarch64")
this.extraArgs.push("-Zbuild-std=core,alloc");
}

buildFlags() {
Expand All @@ -28,7 +36,7 @@ export class KernelBuilder {
'--cfg=board="qemu"',
`--cfg=driver="kvirtio,kgoldfish-rtc,ns16550a"`
];

this.rustflags += ' ' + rustflags.join(" ");
}

Expand All @@ -42,15 +50,18 @@ export class KernelBuilder {
"--release",
"--target",
targetMap[this.arch],
...this.extraArgs
],
env: {
...Deno.env.toObject(),
ROOT_MANIFEST_DIR: Deno.cwd() + "/",
MOUNT_IMG_PATH: "mount.img",
HEAP_SIZE: "0x0180_0000",
BOARD: "qemu",
RUSTFLAGS: this.rustflags
RUSTFLAGS: this.rustflags,
LOG: this.logLvl
},
});
});
const code = await buildProc.spawn().status;
if(!code.success) {
console.error("Failed to build the kernel");
Expand All @@ -59,16 +70,12 @@ export class KernelBuilder {
}

async convertBin() {
const objcopyProc = new Deno.Command("rust-objcopy", {
args: [
`--binary-architecture=${this.arch}`,
this.elfPath,
"--strip-all",
"-O",
"binary",
this.binPath
]
});
await objcopyProc.spawn().status;
await runCommand(`
rust-objcopy --binary-architecture=${this.arch}
${this.elfPath}
--strip-all
-O binary
${this.binPath}
`).spawn().status;
}
}
15 changes: 15 additions & 0 deletions scripts/runHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export function parseArgsString(cmdLine: string): string[] {
return cmdLine.trim().split(/\s+/);
}

export function runCommand(cmdLine: string): Deno.Command {
const args = parseArgsString(cmdLine);
return new Deno.Command(args[0], {
args: args.slice(1)
});
}

export function testParse() {
const args = parseArgsString("qemu-system-x86_64 --arch x86_64 --log-level info");
console.log(args);
}

0 comments on commit ba0d31c

Please sign in to comment.