forked from rcore-os/zCore
Move the ziron libos entry point to zCore directory
This commit is contained in:
parent
806c9d104b
commit
169088dc31
|
@ -47,7 +47,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
crate: cargo-binutils
|
crate: cargo-binutils
|
||||||
version: latest
|
version: latest
|
||||||
use-tool-cache: true
|
|
||||||
- name: Build linux LibOS
|
- name: Build linux LibOS
|
||||||
run: cargo build --features "linux libos"
|
run: cargo build --features "linux libos"
|
||||||
- name: Build zircon LibOS
|
- name: Build zircon LibOS
|
||||||
|
@ -257,7 +256,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
crate: cargo-binutils
|
crate: cargo-binutils
|
||||||
version: latest
|
version: latest
|
||||||
use-tool-cache: true
|
|
||||||
- name: Install cargo tools and qemu-system-riscv64
|
- name: Install cargo tools and qemu-system-riscv64
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
|
|
|
@ -44,9 +44,17 @@ pub struct U128(pub [u64; 2]);
|
||||||
|
|
||||||
impl fmt::Debug for U128 {
|
impl fmt::Debug for U128 {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{:#016x}{:016x}", self.0[1], self.0[0])
|
write!(f, "{:#016x}_{:016x}", self.0[1], self.0[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "libos")]
|
cfg_if! {
|
||||||
pub use trapframe::syscall_fn_entry as syscall_entry;
|
if #[cfg(feature = "libos")] {
|
||||||
|
pub use trapframe::syscall_fn_entry as syscall_entry;
|
||||||
|
} else {
|
||||||
|
pub use dummpy_syscall_entry as syscall_entry;
|
||||||
|
pub fn dummpy_syscall_entry() {
|
||||||
|
unreachable!("dummpy_syscall_entry")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,15 +2,6 @@ use crate::{KernelConfig, KernelHandler, KCONFIG, KHANDLER};
|
||||||
|
|
||||||
hal_fn_impl! {
|
hal_fn_impl! {
|
||||||
impl mod crate::hal_fn::boot {
|
impl mod crate::hal_fn::boot {
|
||||||
fn cmdline() -> String {
|
|
||||||
let root_proc = std::env::args().skip(1).collect::<Vec<_>>().join("?");
|
|
||||||
let mut cmdline = format!("ROOTPROC={}", root_proc);
|
|
||||||
if let Ok(level) = std::env::var("LOG") {
|
|
||||||
cmdline += &format!(":LOG={}", level);
|
|
||||||
}
|
|
||||||
cmdline
|
|
||||||
}
|
|
||||||
|
|
||||||
fn primary_init_early(cfg: KernelConfig, handler: &'static impl KernelHandler) {
|
fn primary_init_early(cfg: KernelConfig, handler: &'static impl KernelHandler) {
|
||||||
KCONFIG.init_once_by(cfg);
|
KCONFIG.init_once_by(cfg);
|
||||||
KHANDLER.init_once_by(handler);
|
KHANDLER.init_once_by(handler);
|
||||||
|
|
|
@ -5,10 +5,12 @@ use std::path::Path;
|
||||||
async fn main() {
|
async fn main() {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
kernel_hal::init();
|
kernel_hal::init();
|
||||||
|
|
||||||
let args = env::args().skip(1).collect();
|
let args = env::args().skip(1).collect();
|
||||||
let envs = vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin".into()];
|
let envs = vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin".into()];
|
||||||
let rootfs_path = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("../rootfs");
|
let rootfs_path = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("../rootfs");
|
||||||
let hostfs = rcore_fs_hostfs::HostFS::new(rootfs_path);
|
let hostfs = rcore_fs_hostfs::HostFS::new(rootfs_path);
|
||||||
|
|
||||||
let proc = linux_loader::run(args, envs, hostfs);
|
let proc = linux_loader::run(args, envs, hostfs);
|
||||||
let code = proc.wait_for_exit().await;
|
let code = proc.wait_for_exit().await;
|
||||||
std::process::exit(code as i32);
|
std::process::exit(code as i32);
|
||||||
|
|
|
@ -35,10 +35,7 @@ pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) ->
|
||||||
let proc = Process::create_linux(&job, rootfs.clone()).unwrap();
|
let proc = Process::create_linux(&job, rootfs.clone()).unwrap();
|
||||||
let thread = Thread::create_linux(&proc).unwrap();
|
let thread = Thread::create_linux(&proc).unwrap();
|
||||||
let loader = LinuxElfLoader {
|
let loader = LinuxElfLoader {
|
||||||
#[cfg(feature = "libos")]
|
|
||||||
syscall_entry: kernel_hal::context::syscall_entry as usize,
|
syscall_entry: kernel_hal::context::syscall_entry as usize,
|
||||||
#[cfg(not(feature = "libos"))]
|
|
||||||
syscall_entry: 0,
|
|
||||||
stack_pages: 8,
|
stack_pages: 8,
|
||||||
root_inode: rootfs.root_inode(),
|
root_inode: rootfs.root_inode(),
|
||||||
};
|
};
|
||||||
|
@ -181,10 +178,7 @@ async fn handle_syscall(thread: &CurrentThread, regs: &mut GeneralRegs) {
|
||||||
let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9];
|
let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9];
|
||||||
let mut syscall = Syscall {
|
let mut syscall = Syscall {
|
||||||
thread,
|
thread,
|
||||||
#[cfg(feature = "libos")]
|
|
||||||
syscall_entry: kernel_hal::context::syscall_entry as usize,
|
syscall_entry: kernel_hal::context::syscall_entry as usize,
|
||||||
#[cfg(not(feature = "libos"))]
|
|
||||||
syscall_entry: 0,
|
|
||||||
thread_fn,
|
thread_fn,
|
||||||
regs,
|
regs,
|
||||||
};
|
};
|
||||||
|
@ -211,10 +205,7 @@ async fn handle_syscall(thread: &CurrentThread, cx: &mut UserContext) {
|
||||||
|
|
||||||
let mut syscall = Syscall {
|
let mut syscall = Syscall {
|
||||||
thread,
|
thread,
|
||||||
#[cfg(feature = "libos")]
|
|
||||||
syscall_entry: kernel_hal::context::syscall_entry as usize,
|
syscall_entry: kernel_hal::context::syscall_entry as usize,
|
||||||
#[cfg(not(feature = "libos"))]
|
|
||||||
syscall_entry: 0,
|
|
||||||
context: cx,
|
context: cx,
|
||||||
thread_fn,
|
thread_fn,
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,7 @@ def print_cases(cases, file=None):
|
||||||
print(case, file=file)
|
print(case, file=file)
|
||||||
|
|
||||||
|
|
||||||
subprocess.run("cd .. && cargo build -p zcore --release --features 'libos linux'",
|
subprocess.run("cd .. && cargo build -p zcore --release --features 'linux libos'",
|
||||||
shell=True, check=True)
|
shell=True, check=True)
|
||||||
|
|
||||||
for path in sorted(glob.glob("../rootfs/libc-test/src/*/*.exe")):
|
for path in sorted(glob.glob("../rootfs/libc-test/src/*/*.exe")):
|
||||||
|
|
|
@ -5,15 +5,15 @@ import argparse
|
||||||
|
|
||||||
TIMEOUT = 300
|
TIMEOUT = 300
|
||||||
ZIRCON_LOADER_PATH = 'zircon-loader'
|
ZIRCON_LOADER_PATH = 'zircon-loader'
|
||||||
PREBUILT_PATH = '../prebuilt/zircon/x64'
|
ZBI_PATH = '../prebuilt/zircon/x64/core-tests.zbi'
|
||||||
CMDLINE_BASE = 'LOG=warn:userboot=test/core-standalone-test:userboot.shutdown:core-tests='
|
CMDLINE_BASE = 'LOG=warn:userboot=test/core-standalone-test:userboot.shutdown:core-tests='
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('testcase', nargs=1)
|
parser.add_argument('testcase', nargs=1)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
child = pexpect.spawn("cargo run -p '%s' -- '%s' '%s' --debug " %
|
child = pexpect.spawn("cargo run -p zcore --features 'zircon libos' -- '%s' '%s'" %
|
||||||
(ZIRCON_LOADER_PATH, PREBUILT_PATH, CMDLINE_BASE+args.testcase[0]),
|
(ZBI_PATH, CMDLINE_BASE+args.testcase[0]),
|
||||||
timeout=TIMEOUT, encoding='utf-8')
|
timeout=TIMEOUT, encoding='utf-8')
|
||||||
|
|
||||||
child.logfile = sys.stdout
|
child.logfile = sys.stdout
|
||||||
|
|
|
@ -11,7 +11,7 @@ RESULT_FILE = BASE + 'test-result-libos.txt'
|
||||||
CHECK_FILE = BASE + 'test-check-passed.txt'
|
CHECK_FILE = BASE + 'test-check-passed.txt'
|
||||||
TEST_CASE_ALL = BASE + 'testcases-all.txt'
|
TEST_CASE_ALL = BASE + 'testcases-all.txt'
|
||||||
TEST_CASE_EXCEPTION = BASE + 'testcases-failed-libos.txt'
|
TEST_CASE_EXCEPTION = BASE + 'testcases-failed-libos.txt'
|
||||||
PREBUILT_PATH = '../prebuilt/zircon/x64'
|
ZBI_PATH = '../prebuilt/zircon/x64/core-tests.zbi'
|
||||||
CMDLINE_BASE = 'LOG=warn:userboot=test/core-standalone-test:userboot.shutdown:core-tests='
|
CMDLINE_BASE = 'LOG=warn:userboot=test/core-standalone-test:userboot.shutdown:core-tests='
|
||||||
|
|
||||||
class Tee:
|
class Tee:
|
||||||
|
@ -40,9 +40,9 @@ with open(TEST_CASE_EXCEPTION, "r") as tcf:
|
||||||
exception_case = set([case.strip() for case in tcf.readlines()])
|
exception_case = set([case.strip() for case in tcf.readlines()])
|
||||||
check_case = all_case - exception_case
|
check_case = all_case - exception_case
|
||||||
|
|
||||||
for line in check_case:
|
for line in check_case:
|
||||||
child = pexpect.spawn("cargo run -p '%s' -- '%s' '%s' --debug" %
|
child = pexpect.spawn("cargo run -p zcore --features 'zircon libos' -- '%s' '%s'" %
|
||||||
(ZIRCON_LOADER_PATH, PREBUILT_PATH, CMDLINE_BASE+line),
|
(ZBI_PATH, CMDLINE_BASE+line),
|
||||||
timeout=TIMEOUT, encoding='utf-8')
|
timeout=TIMEOUT, encoding='utf-8')
|
||||||
|
|
||||||
child.logfile = Tee(OUTPUT_FILE, 'a')
|
child.logfile = Tee(OUTPUT_FILE, 'a')
|
||||||
|
|
|
@ -24,7 +24,7 @@ link_user_img = ["init_ram_disk"]
|
||||||
zircon = ["zircon-loader"]
|
zircon = ["zircon-loader"]
|
||||||
linux = ["linux-loader", "linux-object", "rcore-fs", "rcore-fs-sfs"]
|
linux = ["linux-loader", "linux-object", "rcore-fs", "rcore-fs-sfs"]
|
||||||
|
|
||||||
libos = ["async-std", "chrono", "rcore-fs-hostfs", "linux-loader/libos"]
|
libos = ["async-std", "chrono", "rcore-fs-hostfs", "linux-loader/libos", "zircon-loader/libos"]
|
||||||
board_qemu = []
|
board_qemu = []
|
||||||
board_d1 = ["link_user_img"]
|
board_d1 = ["link_user_img"]
|
||||||
|
|
||||||
|
|
|
@ -8,21 +8,44 @@ LINUX ?=
|
||||||
LIBOS ?=
|
LIBOS ?=
|
||||||
GRAPHIC ?=
|
GRAPHIC ?=
|
||||||
HYPERVISOR ?=
|
HYPERVISOR ?=
|
||||||
SMP ?= 1
|
|
||||||
ACCEL ?=
|
|
||||||
V ?=
|
V ?=
|
||||||
|
|
||||||
USER ?=
|
USER ?=
|
||||||
ZBI ?= bringup
|
ZBI ?= bringup
|
||||||
CMDLINE ?=
|
CMDLINE ?=
|
||||||
ARGS ?= /bin/busybox
|
|
||||||
|
SMP ?= 1
|
||||||
|
ACCEL ?=
|
||||||
|
|
||||||
OBJDUMP ?= rust-objdump --print-imm-hex --x86-asm-syntax=intel
|
OBJDUMP ?= rust-objdump --print-imm-hex --x86-asm-syntax=intel
|
||||||
OBJCOPY ?= rust-objcopy --binary-architecture=$(ARCH)
|
OBJCOPY ?= rust-objcopy --binary-architecture=$(ARCH)
|
||||||
|
|
||||||
|
ifeq ($(LINUX), 1)
|
||||||
|
user_img := $(ARCH).img
|
||||||
|
else ifeq ($(USER), 1)
|
||||||
|
user_img := ../zircon-user/target/zcore-user.zbi
|
||||||
|
else
|
||||||
|
user_img := ../prebuilt/zircon/x64/$(ZBI).zbi
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(PLATFORM), libos)
|
||||||
|
LIBOS := 1
|
||||||
|
endif
|
||||||
|
ifeq ($(LIBOS), 1)
|
||||||
|
build_path := ../target/$(MODE)
|
||||||
|
PLATFORM := libos
|
||||||
|
ifeq ($(LINUX), 1)
|
||||||
|
ARGS ?= /bin/busybox
|
||||||
|
else
|
||||||
|
ARGS ?= $(user_img) $(CMDLINE)
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
build_path := ../target/$(ARCH)/$(MODE)
|
||||||
|
endif
|
||||||
|
|
||||||
################ Internal variables ################
|
################ Internal variables ################
|
||||||
|
|
||||||
qemu := qemu-system-$(ARCH)
|
qemu := qemu-system-$(ARCH)
|
||||||
build_path := ../target/$(ARCH)/$(MODE)
|
|
||||||
kernel_elf := $(build_path)/zcore
|
kernel_elf := $(build_path)/zcore
|
||||||
kernel_img := $(build_path)/zcore.bin
|
kernel_img := $(build_path)/zcore.bin
|
||||||
esp := $(build_path)/esp
|
esp := $(build_path)/esp
|
||||||
|
@ -35,13 +58,6 @@ else
|
||||||
sed := sed -i
|
sed := sed -i
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(LINUX), 1)
|
|
||||||
user_img := $(ARCH).img
|
|
||||||
else ifeq ($(USER), 1)
|
|
||||||
user_img := ../zircon-user/target/zcore-user.zbi
|
|
||||||
else
|
|
||||||
user_img := ../prebuilt/zircon/x64/$(ZBI).zbi
|
|
||||||
endif
|
|
||||||
|
|
||||||
################ Export environments ###################
|
################ Export environments ###################
|
||||||
|
|
||||||
|
@ -57,10 +73,6 @@ else
|
||||||
features := zircon
|
features := zircon
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(PLATFORM), libos)
|
|
||||||
LIBOS := 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(LIBOS), 1)
|
ifeq ($(LIBOS), 1)
|
||||||
ifneq ($(ARCH), $(shell uname -m))
|
ifneq ($(ARCH), $(shell uname -m))
|
||||||
$(error "ARCH" must be "$(shell uname -m)" for libos mode)
|
$(error "ARCH" must be "$(shell uname -m)" for libos mode)
|
||||||
|
@ -170,7 +182,7 @@ run:
|
||||||
test:
|
test:
|
||||||
cargo test $(build_args)
|
cargo test $(build_args)
|
||||||
debug: build
|
debug: build
|
||||||
gdb --args ../target/$(MODE)/zcore $(ARGS)
|
gdb --args $(kernel_elf) $(ARGS)
|
||||||
else
|
else
|
||||||
build: $(kernel_img)
|
build: $(kernel_img)
|
||||||
run: build justrun
|
run: build justrun
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn init_ram_disk() -> &'static mut [u8] {
|
fn init_ram_disk() -> &'static mut [u8] {
|
||||||
if cfg!(feature = "link_user_img") {
|
if cfg!(feature = "link_user_img") {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn _user_img_start();
|
fn _user_img_start();
|
||||||
|
@ -33,8 +33,8 @@ cfg_if! {
|
||||||
|
|
||||||
#[cfg(not(feature = "libos"))]
|
#[cfg(not(feature = "libos"))]
|
||||||
pub fn rootfs() -> Arc<dyn FileSystem> {
|
pub fn rootfs() -> Arc<dyn FileSystem> {
|
||||||
|
use linux_object::fs::rcore_fs_wrapper::{Block, BlockCache, MemBuf};
|
||||||
use rcore_fs::dev::Device;
|
use rcore_fs::dev::Device;
|
||||||
use linux_object::fs::rcore_fs_wrapper::{MemBuf, Block, BlockCache};
|
|
||||||
|
|
||||||
let device: Arc<dyn Device> = if cfg!(feature = "init_ram_disk") {
|
let device: Arc<dyn Device> = if cfg!(feature = "init_ram_disk") {
|
||||||
Arc::new(MemBuf::new(init_ram_disk()))
|
Arc::new(MemBuf::new(init_ram_disk()))
|
||||||
|
@ -45,6 +45,22 @@ cfg_if! {
|
||||||
info!("Opening the rootfs...");
|
info!("Opening the rootfs...");
|
||||||
rcore_fs_sfs::SimpleFileSystem::open(device).expect("failed to open device SimpleFS")
|
rcore_fs_sfs::SimpleFileSystem::open(device).expect("failed to open device SimpleFS")
|
||||||
}
|
}
|
||||||
|
} else if #[cfg(feature = "zircon")] {
|
||||||
|
|
||||||
|
#[cfg(feature = "libos")]
|
||||||
|
pub fn zbi() -> impl AsRef<[u8]> {
|
||||||
|
let args = std::env::args().collect::<Vec<_>>();
|
||||||
|
if args.len() < 2 {
|
||||||
|
println!("Usage: {} ZBI_FILE [CMDLINE]", args[0]);
|
||||||
|
std::process::exit(-1);
|
||||||
|
}
|
||||||
|
std::fs::read(&args[1]).expect("failed to read zbi file")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "libos"))]
|
||||||
|
pub fn zbi() -> impl AsRef<[u8]> {
|
||||||
|
init_ram_disk()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,30 +27,23 @@ fn primary_main(config: kernel_hal::KernelConfig) {
|
||||||
memory::init_heap();
|
memory::init_heap();
|
||||||
kernel_hal::primary_init_early(config, &handler::ZcoreKernelHandler);
|
kernel_hal::primary_init_early(config, &handler::ZcoreKernelHandler);
|
||||||
|
|
||||||
let cmdline = kernel_hal::boot::cmdline();
|
let options = utils::boot_options();
|
||||||
let boot_options = utils::parse_cmdline(&cmdline);
|
logging::set_max_level(&options.log_level);
|
||||||
logging::set_max_level(boot_options.get("LOG").unwrap_or(&""));
|
info!("Boot options: {:#?}", options);
|
||||||
info!("Boot options: {:#?}", boot_options);
|
|
||||||
|
|
||||||
memory::init_frame_allocator(&kernel_hal::mem::free_pmem_regions());
|
memory::init_frame_allocator(&kernel_hal::mem::free_pmem_regions());
|
||||||
kernel_hal::primary_init();
|
kernel_hal::primary_init();
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "linux")] {
|
if #[cfg(feature = "linux")] {
|
||||||
let args = boot_options
|
let args = options.root_proc.split('?').map(Into::into).collect(); // parse "arg0?arg1?arg2"
|
||||||
.get("ROOTPROC").unwrap_or(&"/bin/busybox?sh")
|
|
||||||
.split('?').map(Into::into).collect(); // parse "arg0?arg1?arg2"
|
|
||||||
let envs = alloc::vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin".into()];
|
let envs = alloc::vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin".into()];
|
||||||
let rootfs = fs::rootfs();
|
let rootfs = fs::rootfs();
|
||||||
let proc = linux_loader::run(args, envs, rootfs);
|
let proc = linux_loader::run(args, envs, rootfs);
|
||||||
utils::wait_for_exit(Some(proc))
|
utils::wait_for_exit(Some(proc))
|
||||||
} else if #[cfg(feature = "zircon")] {
|
} else if #[cfg(feature = "zircon")] {
|
||||||
let images = zircon_loader::Images::<&[u8]> {
|
let zbi = fs::zbi();
|
||||||
userboot: include_bytes!("../../prebuilt/zircon/x64/userboot.so"),
|
let proc = zircon_loader::run_userboot(zbi, &options.cmdline);
|
||||||
vdso: include_bytes!("../../prebuilt/zircon/x64/libzircon.so"),
|
|
||||||
zbi: fs::init_ram_disk(),
|
|
||||||
};
|
|
||||||
let proc = zircon_loader::run_userboot(&images, &cmdline);
|
|
||||||
utils::wait_for_exit(Some(proc))
|
utils::wait_for_exit(Some(proc))
|
||||||
} else {
|
} else {
|
||||||
panic!("One of the features `linux` or `zircon` must be specified!");
|
panic!("One of the features `linux` or `zircon` must be specified!");
|
||||||
|
|
|
@ -1,27 +1,80 @@
|
||||||
use alloc::{collections::BTreeMap, sync::Arc};
|
#![allow(dead_code)]
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
|
use alloc::{collections::BTreeMap, string::String, sync::Arc};
|
||||||
use zircon_object::task::Process;
|
use zircon_object::task::Process;
|
||||||
|
|
||||||
pub type BootOptions<'a> = BTreeMap<&'a str, &'a str>;
|
#[derive(Debug)]
|
||||||
|
pub struct BootOptions {
|
||||||
|
pub cmdline: String,
|
||||||
|
pub log_level: String,
|
||||||
|
#[cfg(feature = "linux")]
|
||||||
|
pub root_proc: String,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_cmdline(cmdline: &str) -> BootOptions {
|
fn parse_cmdline(cmdline: &str) -> BTreeMap<&str, &str> {
|
||||||
let mut args = BootOptions::new();
|
let mut options = BTreeMap::new();
|
||||||
for opt in cmdline.split(':') {
|
for opt in cmdline.split(':') {
|
||||||
// parse "key=value"
|
// parse "key=value"
|
||||||
let mut iter = opt.trim().splitn(2, '=');
|
let mut iter = opt.trim().splitn(2, '=');
|
||||||
if let Some(key) = iter.next() {
|
if let Some(key) = iter.next() {
|
||||||
if let Some(value) = iter.next() {
|
if let Some(value) = iter.next() {
|
||||||
args.insert(key.trim(), value.trim());
|
options.insert(key.trim(), value.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn boot_options() -> BootOptions {
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "libos")] {
|
||||||
|
let log_level = std::env::var("LOG").unwrap_or_default();
|
||||||
|
let cmdline = if cfg!(feature = "zircon") {
|
||||||
|
std::env::args().nth(2).unwrap_or_default()
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
|
BootOptions {
|
||||||
|
cmdline,
|
||||||
|
log_level,
|
||||||
|
#[cfg(feature = "linux")]
|
||||||
|
root_proc: std::env::args().skip(1).collect::<Vec<_>>().join("?"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let cmdline = kernel_hal::boot::cmdline();
|
||||||
|
let options = parse_cmdline(&cmdline);
|
||||||
|
BootOptions {
|
||||||
|
cmdline: cmdline.clone(),
|
||||||
|
log_level: String::from(*options.get("LOG").unwrap_or(&"")),
|
||||||
|
#[cfg(feature = "linux")]
|
||||||
|
root_proc: String::from(*options.get("ROOTPROC").unwrap_or(&"/bin/busybox?sh")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
pub fn wait_for_exit(proc: Option<Arc<Process>>) -> ! {
|
pub fn wait_for_exit(proc: Option<Arc<Process>>) -> ! {
|
||||||
#[cfg(feature = "libos")]
|
#[cfg(feature = "libos")]
|
||||||
if let Some(proc) = proc {
|
if let Some(proc) = proc {
|
||||||
let future = async move { proc.wait_for_exit().await };
|
let future = async move {
|
||||||
|
use zircon_object::object::{KernelObject, Signal};
|
||||||
|
let object: Arc<dyn KernelObject> = proc.clone();
|
||||||
|
let signal = if cfg!(feature = "zircon") {
|
||||||
|
Signal::USER_SIGNAL_0
|
||||||
|
} else {
|
||||||
|
Signal::PROCESS_TERMINATED
|
||||||
|
};
|
||||||
|
object.wait_signal(signal).await;
|
||||||
|
let code = proc.exit_code().unwrap_or(-1);
|
||||||
|
info!(
|
||||||
|
"process {:?}({}) exited with code {:?}",
|
||||||
|
proc.name(),
|
||||||
|
proc.id(),
|
||||||
|
code
|
||||||
|
);
|
||||||
|
code
|
||||||
|
};
|
||||||
|
|
||||||
// If the graphic mode is on, run the process in another thread.
|
// If the graphic mode is on, run the process in another thread.
|
||||||
#[cfg(feature = "graphic")]
|
#[cfg(feature = "graphic")]
|
||||||
|
|
|
@ -9,15 +9,16 @@ description = "Zircon user program (userboot) loader"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
cfg-if = "1.0"
|
||||||
xmas-elf = "0.7"
|
xmas-elf = "0.7"
|
||||||
zircon-object = { path = "../zircon-object", features = ["elf"] }
|
zircon-object = { path = "../zircon-object", features = ["elf"] }
|
||||||
zircon-syscall = { path = "../zircon-syscall" }
|
zircon-syscall = { path = "../zircon-syscall" }
|
||||||
kernel-hal = { path = "../kernel-hal" }
|
kernel-hal = { path = "../kernel-hal" }
|
||||||
env_logger = { version = "0.8", optional = true }
|
|
||||||
structopt = { version = "0.3", default-features = false, optional = true }
|
|
||||||
async-std = { version = "1.10", features = ["attributes"], optional = true }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "libos"]
|
default = ["libos"]
|
||||||
libos = ["kernel-hal/libos"]
|
libos = ["kernel-hal/libos", "zircon-object/aspace-separate", "zircon-syscall/std"]
|
||||||
std = ["env_logger", "structopt", "async-std", "zircon-object/aspace-separate", "zircon-syscall/std"]
|
|
||||||
|
[dev-dependencies]
|
||||||
|
env_logger = "0.9"
|
||||||
|
async-std = { version = "1.10", features = ["attributes"] }
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use zircon_object::object::{KernelObject, Signal};
|
||||||
|
|
||||||
|
#[async_std::main]
|
||||||
|
async fn main() {
|
||||||
|
env_logger::init();
|
||||||
|
kernel_hal::init();
|
||||||
|
|
||||||
|
let args = std::env::args().collect::<Vec<_>>();
|
||||||
|
if args.len() < 2 {
|
||||||
|
println!("Usage: {} ZBI_FILE [CMDLINE]", args[0]);
|
||||||
|
std::process::exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let zbi = std::fs::read(&args[1]).expect("failed to read zbi file");
|
||||||
|
let cmdline = args.get(2).map(String::as_str).unwrap_or("");
|
||||||
|
|
||||||
|
let proc: Arc<dyn KernelObject> = zircon_loader::run_userboot(zbi, cmdline);
|
||||||
|
proc.wait_signal(Signal::USER_SIGNAL_0).await;
|
||||||
|
}
|
|
@ -32,14 +32,34 @@ const K_COUNTERS: usize = 10;
|
||||||
const K_FISTINSTRUMENTATIONDATA: usize = 11;
|
const K_FISTINSTRUMENTATIONDATA: usize = 11;
|
||||||
const K_HANDLECOUNT: usize = 15;
|
const K_HANDLECOUNT: usize = 15;
|
||||||
|
|
||||||
/// Program images to run.
|
macro_rules! boot_firmware {
|
||||||
pub struct Images<T: AsRef<[u8]>> {
|
($name: expr) => {{
|
||||||
pub userboot: T,
|
cfg_if::cfg_if! {
|
||||||
pub vdso: T,
|
if #[cfg(target_arch = "x86_64")] {
|
||||||
pub zbi: T,
|
boot_firmware!($name, "../../prebuilt/zircon/x64")
|
||||||
|
} else if #[cfg(target_arch = "aarch64")] {
|
||||||
|
boot_firmware!($name, "../../prebuilt/zircon/arm64")
|
||||||
|
} else {
|
||||||
|
compile_error!("Unsupported architecture for zircon mode!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
($name: expr, $base_dir: expr) => {{
|
||||||
|
#[cfg(feature = "libos")]
|
||||||
|
{
|
||||||
|
include_bytes!(concat!($base_dir, "/", $name, "-libos.so"))
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "libos"))]
|
||||||
|
{
|
||||||
|
include_bytes!(concat!($base_dir, "/", $name, ".so"))
|
||||||
|
}
|
||||||
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Process> {
|
pub fn run_userboot(zbi: impl AsRef<[u8]>, cmdline: &str) -> Arc<Process> {
|
||||||
|
let userboot = boot_firmware!("userboot");
|
||||||
|
let vdso = boot_firmware!("libzircon");
|
||||||
|
|
||||||
let job = Job::root();
|
let job = Job::root();
|
||||||
let proc = Process::create(&job, "userboot").unwrap();
|
let proc = Process::create(&job, "userboot").unwrap();
|
||||||
let thread = Thread::create(&proc, "userboot").unwrap();
|
let thread = Thread::create(&proc, "userboot").unwrap();
|
||||||
|
@ -54,7 +74,7 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
|
||||||
|
|
||||||
// userboot
|
// userboot
|
||||||
let (entry, userboot_size) = {
|
let (entry, userboot_size) = {
|
||||||
let elf = ElfFile::new(images.userboot.as_ref()).unwrap();
|
let elf = ElfFile::new(userboot).unwrap();
|
||||||
let size = elf.load_segment_size();
|
let size = elf.load_segment_size();
|
||||||
let vmar = vmar
|
let vmar = vmar
|
||||||
.allocate(None, size, VmarFlags::CAN_MAP_RXW, PAGE_SIZE)
|
.allocate(None, size, VmarFlags::CAN_MAP_RXW, PAGE_SIZE)
|
||||||
|
@ -65,9 +85,9 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
|
||||||
|
|
||||||
// vdso
|
// vdso
|
||||||
let vdso_vmo = {
|
let vdso_vmo = {
|
||||||
let elf = ElfFile::new(images.vdso.as_ref()).unwrap();
|
let elf = ElfFile::new(vdso).unwrap();
|
||||||
let vdso_vmo = VmObject::new_paged(images.vdso.as_ref().len() / PAGE_SIZE + 1);
|
let vdso_vmo = VmObject::new_paged(vdso.len() / PAGE_SIZE + 1);
|
||||||
vdso_vmo.write(0, images.vdso.as_ref()).unwrap();
|
vdso_vmo.write(0, vdso).unwrap();
|
||||||
let size = elf.load_segment_size();
|
let size = elf.load_segment_size();
|
||||||
let vmar = vmar
|
let vmar = vmar
|
||||||
.allocate_at(
|
.allocate_at(
|
||||||
|
@ -78,7 +98,7 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
vmar.map_from_elf(&elf, vdso_vmo.clone()).unwrap();
|
vmar.map_from_elf(&elf, vdso_vmo.clone()).unwrap();
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "libos")]
|
||||||
{
|
{
|
||||||
let offset = elf
|
let offset = elf
|
||||||
.get_symbol_address("zcore_syscall_entry")
|
.get_symbol_address("zcore_syscall_entry")
|
||||||
|
@ -94,8 +114,8 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
|
||||||
|
|
||||||
// zbi
|
// zbi
|
||||||
let zbi_vmo = {
|
let zbi_vmo = {
|
||||||
let vmo = VmObject::new_paged(images.zbi.as_ref().len() / PAGE_SIZE + 1);
|
let vmo = VmObject::new_paged(zbi.as_ref().len() / PAGE_SIZE + 1);
|
||||||
vmo.write(0, images.zbi.as_ref()).unwrap();
|
vmo.write(0, zbi.as_ref()).unwrap();
|
||||||
vmo.set_name("zbi");
|
vmo.set_name("zbi");
|
||||||
vmo
|
vmo
|
||||||
};
|
};
|
||||||
|
@ -267,7 +287,7 @@ async fn handle_syscall(thread: &CurrentThread) {
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
let num = regs.x16 as u32;
|
let num = regs.x16 as u32;
|
||||||
// LibOS: Function call ABI
|
// LibOS: Function call ABI
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "libos")]
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
let args = unsafe {
|
let args = unsafe {
|
||||||
let a6 = (regs.rsp as *const usize).read();
|
let a6 = (regs.rsp as *const usize).read();
|
||||||
|
@ -277,7 +297,7 @@ async fn handle_syscall(thread: &CurrentThread) {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
// RealOS: Zircon syscall ABI
|
// RealOS: Zircon syscall ABI
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "libos"))]
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
let args = [
|
let args = [
|
||||||
regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9, regs.r12, regs.r13,
|
regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9, regs.r12, regs.r13,
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
#![deny(warnings, unused_must_use)]
|
|
||||||
|
|
||||||
extern crate log;
|
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use structopt::StructOpt;
|
|
||||||
use zircon_loader::*;
|
|
||||||
use zircon_object::object::*;
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
|
||||||
#[structopt()]
|
|
||||||
struct Opt {
|
|
||||||
#[structopt(parse(from_os_str))]
|
|
||||||
prebuilt_path: PathBuf,
|
|
||||||
|
|
||||||
#[structopt(default_value = "")]
|
|
||||||
cmdline: String,
|
|
||||||
|
|
||||||
#[structopt(short, long)]
|
|
||||||
debug: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_std::main]
|
|
||||||
async fn main() {
|
|
||||||
kernel_hal::init();
|
|
||||||
init_logger();
|
|
||||||
|
|
||||||
let opt = Opt::from_args();
|
|
||||||
let images = open_images(&opt.prebuilt_path, opt.debug).expect("failed to read file");
|
|
||||||
let proc: Arc<dyn KernelObject> = run_userboot(&images, &opt.cmdline);
|
|
||||||
drop(images);
|
|
||||||
|
|
||||||
proc.wait_signal(Signal::USER_SIGNAL_0).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn open_images(path: &Path, debug: bool) -> std::io::Result<Images<Vec<u8>>> {
|
|
||||||
Ok(Images {
|
|
||||||
userboot: std::fs::read(path.join("userboot-libos.so"))?,
|
|
||||||
vdso: std::fs::read(path.join("libzircon-libos.so"))?,
|
|
||||||
zbi: if debug {
|
|
||||||
std::fs::read(path.join("core-tests.zbi"))?
|
|
||||||
} else {
|
|
||||||
std::fs::read(path.join("bringup.zbi"))?
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_logger() {
|
|
||||||
env_logger::builder()
|
|
||||||
.format(|buf, record| {
|
|
||||||
use env_logger::fmt::Color;
|
|
||||||
use log::Level;
|
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
let (tid, pid) = kernel_hal::thread::get_tid();
|
|
||||||
let mut style = buf.style();
|
|
||||||
match record.level() {
|
|
||||||
Level::Trace => style.set_color(Color::Black).set_intense(true),
|
|
||||||
Level::Debug => style.set_color(Color::White),
|
|
||||||
Level::Info => style.set_color(Color::Green),
|
|
||||||
Level::Warn => style.set_color(Color::Yellow),
|
|
||||||
Level::Error => style.set_color(Color::Red).set_bold(true),
|
|
||||||
};
|
|
||||||
let now = kernel_hal::timer::timer_now();
|
|
||||||
let level = style.value(record.level());
|
|
||||||
let args = record.args();
|
|
||||||
writeln!(buf, "[{:?} {:>5} {}:{}] {}", now, level, pid, tid, args)
|
|
||||||
})
|
|
||||||
.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[async_std::test]
|
|
||||||
async fn userboot() {
|
|
||||||
kernel_hal::init();
|
|
||||||
|
|
||||||
let opt = Opt {
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
prebuilt_path: PathBuf::from("../prebuilt/zircon/x64"),
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
prebuilt_path: PathBuf::from("../prebuilt/zircon/arm64"),
|
|
||||||
cmdline: String::from(""),
|
|
||||||
debug: false,
|
|
||||||
};
|
|
||||||
let images = open_images(&opt.prebuilt_path, opt.debug).expect("failed to read file");
|
|
||||||
|
|
||||||
let proc: Arc<dyn KernelObject> = run_userboot(&images, &opt.cmdline);
|
|
||||||
drop(images);
|
|
||||||
|
|
||||||
proc.wait_signal(Signal::PROCESS_TERMINATED).await;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[async_std::test]
|
||||||
|
async fn userboot() {
|
||||||
|
kernel_hal::init();
|
||||||
|
let zbi = std::fs::read("../prebuilt/zircon/x64/bringup.zbi").expect("failed to read zbi file");
|
||||||
|
let proc = zircon_loader::run_userboot(zbi, "");
|
||||||
|
proc.wait_for_exit().await;
|
||||||
|
}
|
|
@ -294,6 +294,15 @@ impl Process {
|
||||||
self.inner.lock().status
|
self.inner.lock().status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get process exit code if it exited, else returns `None`.
|
||||||
|
pub fn exit_code(&self) -> Option<i64> {
|
||||||
|
if let Status::Exited(code) = self.status() {
|
||||||
|
Some(code)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the extension.
|
/// Get the extension.
|
||||||
pub fn ext(&self) -> &Box<dyn Any + Send + Sync> {
|
pub fn ext(&self) -> &Box<dyn Any + Send + Sync> {
|
||||||
&self.ext
|
&self.ext
|
||||||
|
@ -529,17 +538,14 @@ impl Process {
|
||||||
pub async fn wait_for_exit(self: &Arc<Self>) -> i64 {
|
pub async fn wait_for_exit(self: &Arc<Self>) -> i64 {
|
||||||
let object: Arc<dyn KernelObject> = self.clone();
|
let object: Arc<dyn KernelObject> = self.clone();
|
||||||
object.wait_signal(Signal::PROCESS_TERMINATED).await;
|
object.wait_signal(Signal::PROCESS_TERMINATED).await;
|
||||||
if let Status::Exited(code) = self.status() {
|
let code = self.exit_code().expect("process not exited!");
|
||||||
info!(
|
info!(
|
||||||
"process {:?}({}) exited with code {:?}",
|
"process {:?}({}) exited with code {:?}",
|
||||||
self.name(),
|
self.name(),
|
||||||
self.id(),
|
self.id(),
|
||||||
code
|
|
||||||
);
|
|
||||||
code
|
code
|
||||||
} else {
|
);
|
||||||
unreachable!();
|
code
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue