mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Switch to EFI boot and use official release for QEMU and GDB
This commit is contained in:
parent
aea8f38dc1
commit
cdc2b960dc
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
[target.'cfg(target_os = "none")']
|
[target.'cfg(target_os = "none")']
|
||||||
runner = "cargo run --package jinux-build --"
|
runner = "cargo run --package jinux-runner --"
|
||||||
|
|
||||||
[alias]
|
[alias]
|
||||||
kcheck = "check --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
kcheck = "check --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
||||||
|
4
.github/workflows/cargo_check.yml
vendored
4
.github/workflows/cargo_check.yml
vendored
@ -10,9 +10,9 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: jinuxdev/jinux:0.1.2
|
container: jinuxdev/jinux:0.2.0
|
||||||
steps:
|
steps:
|
||||||
- run: echo "Running in jinuxdev/jinux:0.1.2"
|
- run: echo "Running in jinuxdev/jinux:0.2.0"
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
8
.github/workflows/syscall_test.yml
vendored
8
.github/workflows/syscall_test.yml
vendored
@ -10,18 +10,18 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: jinuxdev/jinux:0.1.2
|
container: jinuxdev/jinux:0.2.0
|
||||||
steps:
|
steps:
|
||||||
- run: echo "Running in jinuxdev/jinux:0.1.2"
|
- run: echo "Running in jinuxdev/jinux:0.2.0"
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Syscall Test (Multiboot2)
|
- name: Syscall Test (Multiboot2)
|
||||||
id: syscall_test_mb2
|
id: syscall_test_mb2
|
||||||
run: RUSTFLAGS="-C opt-level=1" make run AUTO_SYSCALL_TEST=1 ENABLE_KVM=0 SKIP_GRUB_MENU=1 BOOT_METHOD=grub-multiboot2
|
run: RUSTFLAGS="-C opt-level=1" make run AUTO_SYSCALL_TEST=1 ENABLE_KVM=0 SKIP_GRUB_MENU=1 BOOT_METHOD=qemu-grub BOOT_PROTOCOL=multiboot2
|
||||||
|
|
||||||
# TODO: include the integration tests for Multiboot/MicroVM/Linux boot methods, which are not ready yet.
|
# TODO: include the integration tests for Multiboot/MicroVM/Linux boot methods, which are not ready yet.
|
||||||
|
|
||||||
# - name: Syscall Test (Linux Boot Protocol)
|
# - name: Syscall Test (Linux Boot Protocol)
|
||||||
# id: syscall_test_lbp
|
# id: syscall_test_lbp
|
||||||
# run: RUSTFLAGS="-C opt-level=1" make run AUTO_SYSCALL_TEST=1 ENABLE_KVM=0 SKIP_GRUB_MENU=1 BOOT_METHOD=grub-linux
|
# run: RUSTFLAGS="-C opt-level=1" make run AUTO_SYSCALL_TEST=1 ENABLE_KVM=0 SKIP_GRUB_MENU=1 BOOT_METHOD=qemu-grub BOOT_PROTOCOL=linux
|
||||||
|
22
Cargo.lock
generated
22
Cargo.lock
generated
@ -599,7 +599,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinux"
|
name = "jinux"
|
||||||
version = "0.1.2"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"component",
|
"component",
|
||||||
"jinux-frame",
|
"jinux-frame",
|
||||||
@ -622,16 +622,6 @@ dependencies = [
|
|||||||
"spin 0.9.8",
|
"spin 0.9.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jinux-build"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"clap",
|
|
||||||
"glob",
|
|
||||||
"rand",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinux-frame"
|
name = "jinux-frame"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -731,6 +721,16 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jinux-runner"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"clap",
|
||||||
|
"glob",
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinux-std"
|
name = "jinux-std"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "jinux"
|
name = "jinux"
|
||||||
version = "0.1.2"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
@ -20,7 +20,7 @@ jinux-framebuffer = { path = "services/comps/framebuffer" }
|
|||||||
[workspace]
|
[workspace]
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"build",
|
"runner",
|
||||||
"framework/jinux-frame",
|
"framework/jinux-frame",
|
||||||
"framework/jinux-frame/src/arch/x86/boot/linux_boot/setup",
|
"framework/jinux-frame/src/arch/x86/boot/linux_boot/setup",
|
||||||
"framework/libs/align_ext",
|
"framework/libs/align_ext",
|
||||||
|
10
Makefile
10
Makefile
@ -1,6 +1,7 @@
|
|||||||
# Make arguments and their defaults
|
# Make arguments and their defaults
|
||||||
AUTO_SYSCALL_TEST ?= 0
|
AUTO_SYSCALL_TEST ?= 0
|
||||||
BOOT_METHOD ?= grub-multiboot2
|
BOOT_METHOD ?= qemu-grub
|
||||||
|
BOOT_PROTOCOL ?= multiboot2
|
||||||
BUILD_SYSCALL_TEST ?= 0
|
BUILD_SYSCALL_TEST ?= 0
|
||||||
EMULATE_IOMMU ?= 0
|
EMULATE_IOMMU ?= 0
|
||||||
ENABLE_KVM ?= 1
|
ENABLE_KVM ?= 1
|
||||||
@ -24,6 +25,7 @@ BUILD_SYSCALL_TEST := 1
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
CARGO_KRUN_ARGS += --boot-method="$(BOOT_METHOD)"
|
CARGO_KRUN_ARGS += --boot-method="$(BOOT_METHOD)"
|
||||||
|
CARGO_KRUN_ARGS += --boot-protocol="$(BOOT_PROTOCOL)"
|
||||||
|
|
||||||
ifeq ($(EMULATE_IOMMU), 1)
|
ifeq ($(EMULATE_IOMMU), 1)
|
||||||
CARGO_KRUN_ARGS += --emulate-iommu
|
CARGO_KRUN_ARGS += --emulate-iommu
|
||||||
@ -54,12 +56,8 @@ endif
|
|||||||
# Pass make variables to all subdirectory makes
|
# Pass make variables to all subdirectory makes
|
||||||
export
|
export
|
||||||
|
|
||||||
export JINUX_BOOT_PROTOCOL=$(BOOT_PROTOCOL)
|
# Toolchain variables that are used when building the Linux setup header
|
||||||
|
|
||||||
# Toolchain variables
|
|
||||||
export CARGO := cargo
|
export CARGO := cargo
|
||||||
export AS := as
|
|
||||||
export CC := gcc
|
|
||||||
export OBJCOPY := objcopy
|
export OBJCOPY := objcopy
|
||||||
|
|
||||||
.PHONY: all setup build tools run test docs check clean
|
.PHONY: all setup build tools run test docs check clean
|
||||||
|
24
README.md
24
README.md
@ -22,7 +22,7 @@ Jinux is unique in practicing the principle of least privilege without sacrifici
|
|||||||
|
|
||||||
As a zero-cost, least-privilege OS, Jinux provides the best of both worlds: the performance of a monolithic kernel and the security of a microkernel. Like a monolithic kernel, the different parts of Jinux can communicate with the most efficient means, e.g., function calls and memory sharing. In the same spirit as a microkernel, the fundamental security properties of the OS depend on a minimum amount of code (i.e., Jinux Framework).
|
As a zero-cost, least-privilege OS, Jinux provides the best of both worlds: the performance of a monolithic kernel and the security of a microkernel. Like a monolithic kernel, the different parts of Jinux can communicate with the most efficient means, e.g., function calls and memory sharing. In the same spirit as a microkernel, the fundamental security properties of the OS depend on a minimum amount of code (i.e., Jinux Framework).
|
||||||
|
|
||||||
## Build and test
|
## Build, test and debug Jinux
|
||||||
|
|
||||||
While most of the code is written in Rust, the project-scope build process is governed by Makefile. The development environment is managed with Docker. Please ensure Docker is installed and can be run without sudo privilege.
|
While most of the code is written in Rust, the project-scope build process is governed by Makefile. The development environment is managed with Docker. Please ensure Docker is installed and can be run without sudo privilege.
|
||||||
|
|
||||||
@ -34,12 +34,12 @@ git clone [repository url]
|
|||||||
|
|
||||||
2. After downloading the source code, run the following command to pull the development image.
|
2. After downloading the source code, run the following command to pull the development image.
|
||||||
```bash
|
```bash
|
||||||
docker pull jinuxdev/jinux:0.1.2
|
docker pull jinuxdev/jinux:0.2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Start the development container.
|
3. Start the development container.
|
||||||
```bash
|
```bash
|
||||||
docker run -it --privileged --network=host --device=/dev/kvm -v `pwd`:/root/jinux jinuxdev/jinux:0.1.2
|
docker run -it --privileged --network=host --device=/dev/kvm -v `pwd`:/root/jinux jinuxdev/jinux:0.2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
**All build and test commands should be run inside the development container.**
|
**All build and test commands should be run inside the development container.**
|
||||||
@ -90,11 +90,27 @@ Then, we can run the following script using the Jinux shell to run all syscall t
|
|||||||
/opt/syscall_test/run_syscall_test.sh
|
/opt/syscall_test/run_syscall_test.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Debug
|
||||||
|
|
||||||
|
To debug Jinux using [QEMU GDB remote debugging](https://qemu-project.gitlab.io/qemu/system/gdb.html), you could compile Jinux in debug mode, start a Jinux instance and run the GDB interactive shell in another terminal.
|
||||||
|
|
||||||
|
To start a QEMU Jinux VM and wait for debugging connection:
|
||||||
|
```bash
|
||||||
|
make run GDB_SERVER=1 ENABLE_KVM=0
|
||||||
|
```
|
||||||
|
|
||||||
|
To get the GDB interactive shell:
|
||||||
|
```bash
|
||||||
|
make run GDB_CLIENT=1
|
||||||
|
```
|
||||||
|
|
||||||
|
Currently, the Jinux runner's debugging interface is exposed by unix socket. Thus there shouldn't be multiple debugging instances in the same container. To add debug symbols for the underlying infrastructures such as UEFI firmware or bootloader, please check the runner's source code for details.
|
||||||
|
|
||||||
## Code organization
|
## Code organization
|
||||||
|
|
||||||
The codebase of Jinux is organized as below.
|
The codebase of Jinux is organized as below.
|
||||||
|
|
||||||
* `build/`: creating a bootable Jinux kernel image along with an initramfs image. It also supports `cargo run` since it is the only package with `main()`.
|
* `runner/`: creating a bootable Jinux kernel image along with an initramfs image. It also supports `cargo run` since it is the only package with `main()`.
|
||||||
* `kernel/`: defining the entry point of the Jinux kernel.
|
* `kernel/`: defining the entry point of the Jinux kernel.
|
||||||
* `framework/`: the privileged half of Jinux (allowed to use `unsafe` keyword)
|
* `framework/`: the privileged half of Jinux (allowed to use `unsafe` keyword)
|
||||||
* `jinux-frame`: providing the safe Rust abstractions for low-level resources like CPU, memory, interrupts, etc;
|
* `jinux-frame`: providing the safe Rust abstractions for low-level resources like CPU, memory, interrupts, etc;
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
search.fs_label grub root
|
|
||||||
if [ -e /boot/grub/grub.cfg ]; then
|
|
||||||
set prefix=($root)/boot/grub
|
|
||||||
configfile /boot/grub/grub.cfg
|
|
||||||
else
|
|
||||||
echo "Could not find a configuration file!"
|
|
||||||
fi
|
|
@ -1,2 +0,0 @@
|
|||||||
pub mod default;
|
|
||||||
pub mod microvm;
|
|
@ -4,6 +4,9 @@
|
|||||||
.section ".boot", "awx"
|
.section ".boot", "awx"
|
||||||
.code32
|
.code32
|
||||||
|
|
||||||
|
// With the 32-bit entry types we should go through a common paging and machine
|
||||||
|
// state setup routine. Thus we make a mark of protocol used in each entrypoint
|
||||||
|
// on the stack.
|
||||||
ENTRYTYPE_MULTIBOOT = 1
|
ENTRYTYPE_MULTIBOOT = 1
|
||||||
ENTRYTYPE_MULTIBOOT2 = 2
|
ENTRYTYPE_MULTIBOOT2 = 2
|
||||||
ENTRYTYPE_LINUX_32 = 3
|
ENTRYTYPE_LINUX_32 = 3
|
||||||
@ -122,6 +125,7 @@ PTE_GLOBAL = (1 << 8)
|
|||||||
// 0xffff8000_40000000 ~ 0xffff8000_7fffffff
|
// 0xffff8000_40000000 ~ 0xffff8000_7fffffff
|
||||||
// 0xffff8000_80000000 ~ 0xffff8000_bfffffff
|
// 0xffff8000_80000000 ~ 0xffff8000_bfffffff
|
||||||
// 0xffff8000_c0000000 ~ 0xffff8000_ffffffff
|
// 0xffff8000_c0000000 ~ 0xffff8000_ffffffff
|
||||||
|
// 0xffff8008_00000000 ~ 0xffff8008_3fffffff
|
||||||
lea edi, [boot_pml4 + 0x100 * 8]
|
lea edi, [boot_pml4 + 0x100 * 8]
|
||||||
lea eax, [boot_pdpt + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
|
lea eax, [boot_pdpt + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
|
||||||
mov dword ptr [edi], eax
|
mov dword ptr [edi], eax
|
||||||
@ -158,6 +162,13 @@ PTE_GLOBAL = (1 << 8)
|
|||||||
mov dword ptr [edi], eax
|
mov dword ptr [edi], eax
|
||||||
mov dword ptr [edi + 4], 0
|
mov dword ptr [edi + 4], 0
|
||||||
|
|
||||||
|
// 1000 00000|000 100000|00 0000000|0 00000000 000
|
||||||
|
// PDPT: 0xffff8008_00000000 ~ 0xffff8008_3fffffff
|
||||||
|
lea edi, [boot_pdpt + 0x20 * 8]
|
||||||
|
lea eax, [boot_pd_32g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
|
||||||
|
mov dword ptr [edi], eax
|
||||||
|
mov dword ptr [edi + 4], 0
|
||||||
|
|
||||||
// PDPT: 0xffffffff_80000000 ~ 0xffffffff_bfffffff
|
// PDPT: 0xffffffff_80000000 ~ 0xffffffff_bfffffff
|
||||||
lea edi, [boot_pdpt + 0x1fe * 8]
|
lea edi, [boot_pdpt + 0x1fe * 8]
|
||||||
lea eax, [boot_pd_0g_1g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
|
lea eax, [boot_pd_0g_1g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
|
||||||
@ -172,27 +183,25 @@ PTE_GLOBAL = (1 << 8)
|
|||||||
|
|
||||||
// Page Directory: map to low 1 GiB * 4 space
|
// Page Directory: map to low 1 GiB * 4 space
|
||||||
lea edi, [boot_pd]
|
lea edi, [boot_pd]
|
||||||
lea eax, [boot_pt + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)]
|
mov eax, (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL | PTE_HUGE) // Map offset 0.
|
||||||
mov ecx, 512 * 4 // (of entries in PD) * (number of PD)
|
mov ecx, 512 * 4 // (of entries in PD) * (number of PD)
|
||||||
|
|
||||||
write_pd_entry:
|
write_pd_entry:
|
||||||
mov dword ptr [edi], eax
|
mov dword ptr [edi], eax
|
||||||
mov dword ptr [edi + 4], 0
|
mov dword ptr [edi + 4], 0
|
||||||
add eax, 0x1000 // 4kiB
|
add eax, 0x200000 // +2MiB
|
||||||
add edi, 8
|
add edi, 8
|
||||||
loop write_pd_entry
|
loop write_pd_entry
|
||||||
|
|
||||||
// Page Table: map to low 4 KiB * 1M space
|
// Page Directory: map to 1 GiB space offset 32GiB
|
||||||
lea edi, [boot_pt]
|
lea edi, [boot_pd_32g]
|
||||||
mov eax, 0x103 // Present, writable, global.
|
mov eax, (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL | PTE_HUGE) // Should +0x800000000 but this is 32-bit.
|
||||||
mov ecx, 512 * 512 * 4 // (of entries in PT) * (number of PT)
|
mov ecx, 512 // (of entries in PD)
|
||||||
|
write_pd_32g_entry:
|
||||||
write_pt_entry:
|
|
||||||
mov dword ptr [edi], eax
|
mov dword ptr [edi], eax
|
||||||
mov dword ptr [edi + 4], 0
|
mov dword ptr [edi + 4], 0x8 // Map offset 32GiB.
|
||||||
add eax, 0x1000 // 4KiB
|
add eax, 0x200000 // +2MiB
|
||||||
add edi, 8
|
add edi, 8
|
||||||
loop write_pt_entry
|
loop write_pd_32g_entry
|
||||||
|
|
||||||
jmp enable_long_mode
|
jmp enable_long_mode
|
||||||
|
|
||||||
@ -258,8 +267,8 @@ boot_pd_2g_3g:
|
|||||||
.skip 4096
|
.skip 4096
|
||||||
boot_pd_3g_4g:
|
boot_pd_3g_4g:
|
||||||
.skip 4096
|
.skip 4096
|
||||||
boot_pt:
|
boot_pd_32g:
|
||||||
.skip 4096 * 512 * 4
|
.skip 4096
|
||||||
boot_page_table_end:
|
boot_page_table_end:
|
||||||
|
|
||||||
boot_stack_bottom:
|
boot_stack_bottom:
|
||||||
@ -299,11 +308,11 @@ long_mode:
|
|||||||
cmp rax, ENTRYTYPE_MULTIBOOT2
|
cmp rax, ENTRYTYPE_MULTIBOOT2
|
||||||
je entry_type_multiboot2
|
je entry_type_multiboot2
|
||||||
cmp rax, ENTRYTYPE_LINUX_32
|
cmp rax, ENTRYTYPE_LINUX_32
|
||||||
je entry_type_pvh_elf
|
je entry_type_linux_32
|
||||||
// Unreachable!
|
// Unreachable!
|
||||||
jmp halt
|
jmp halt
|
||||||
|
|
||||||
entry_type_pvh_elf:
|
entry_type_linux_32:
|
||||||
pop rdi // boot_params ptr
|
pop rdi // boot_params ptr
|
||||||
|
|
||||||
// Clear the frame pointer to stop backtracing here.
|
// Clear the frame pointer to stop backtracing here.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
// The section name is used by the build script to strip and make
|
// The section name is used by the build script to strip and make
|
||||||
// the binary file.
|
// the binary file.
|
||||||
.section ".header", "awx"
|
.section ".header", "ax"
|
||||||
|
|
||||||
// The Linux x86 Boot Protocol header.
|
// The Linux x86 Boot Protocol header.
|
||||||
//
|
//
|
||||||
@ -56,8 +56,8 @@ hardware_subarch_data: .quad 0
|
|||||||
payload_offset: .long 0xabababab # at 0x248/4, to be filled by the runner
|
payload_offset: .long 0xabababab # at 0x248/4, to be filled by the runner
|
||||||
payload_length: .long 0xabababab # at 0x24c/4, to be filled by the runner
|
payload_length: .long 0xabababab # at 0x24c/4, to be filled by the runner
|
||||||
setup_data: .quad 0
|
setup_data: .quad 0
|
||||||
pref_address: .quad 0
|
pref_address: .quad 0x8000000 # 128MiB
|
||||||
init_size: .long 0
|
init_size: .long 0x4000000 # 64MiB
|
||||||
handover_offset: .long 0
|
handover_offset: .long 0
|
||||||
kernel_info_offset: .long 0
|
kernel_info_offset: .long 0
|
||||||
|
|
||||||
|
@ -17,4 +17,4 @@
|
|||||||
"os": "none",
|
"os": "none",
|
||||||
"relocation-model": "static",
|
"relocation-model": "static",
|
||||||
"features": "+soft-float,-sse,-mmx"
|
"features": "+soft-float,-sse,-mmx"
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,9 @@ fn init_acpi_arg(acpi: &'static Once<BootloaderAcpiArg>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn init_framebuffer_info(framebuffer_arg: &'static Once<BootloaderFramebufferArg>) {
|
fn init_framebuffer_info(framebuffer_arg: &'static Once<BootloaderFramebufferArg>) {
|
||||||
let fb_tag = MB2_INFO.get().unwrap().framebuffer_tag().unwrap().unwrap();
|
let Some(Ok(fb_tag)) = MB2_INFO.get().unwrap().framebuffer_tag() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
framebuffer_arg.call_once(|| BootloaderFramebufferArg {
|
framebuffer_arg.call_once(|| BootloaderFramebufferArg {
|
||||||
address: fb_tag.address() as usize,
|
address: fb_tag.address() as usize,
|
||||||
width: fb_tag.width() as usize,
|
width: fb_tag.width() as usize,
|
||||||
@ -122,19 +124,20 @@ fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
|||||||
);
|
);
|
||||||
regions.push(region);
|
regions.push(region);
|
||||||
}
|
}
|
||||||
// Add the framebuffer region since Grub does not specify it.
|
if let Some(Ok(fb_tag)) = MB2_INFO.get().unwrap().framebuffer_tag() {
|
||||||
let fb_tag = MB2_INFO.get().unwrap().framebuffer_tag().unwrap().unwrap();
|
// Add the framebuffer region since Grub does not specify it.
|
||||||
let fb = BootloaderFramebufferArg {
|
let fb = BootloaderFramebufferArg {
|
||||||
address: fb_tag.address() as usize,
|
address: fb_tag.address() as usize,
|
||||||
width: fb_tag.width() as usize,
|
width: fb_tag.width() as usize,
|
||||||
height: fb_tag.height() as usize,
|
height: fb_tag.height() as usize,
|
||||||
bpp: fb_tag.bpp() as usize,
|
bpp: fb_tag.bpp() as usize,
|
||||||
};
|
};
|
||||||
regions.push(MemoryRegion::new(
|
regions.push(MemoryRegion::new(
|
||||||
fb.address,
|
fb.address,
|
||||||
(fb.width * fb.height * fb.bpp + 7) / 8, // round up when divide with 8 (bits/Byte)
|
(fb.width * fb.height * fb.bpp + 7) / 8, // round up when divide with 8 (bits/Byte)
|
||||||
MemoryRegionType::Framebuffer,
|
MemoryRegionType::Framebuffer,
|
||||||
));
|
));
|
||||||
|
}
|
||||||
// Add the kernel region since Grub does not specify it.
|
// Add the kernel region since Grub does not specify it.
|
||||||
// These are physical addresses provided by the linker script.
|
// These are physical addresses provided by the linker script.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(new_uninit)]
|
#![feature(new_uninit)]
|
||||||
#![feature(strict_provenance)]
|
#![feature(strict_provenance)]
|
||||||
//#![feature(link_llvm_intrinsics)]
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(generators)]
|
#![feature(generators)]
|
||||||
#![feature(iter_from_generator)]
|
#![feature(iter_from_generator)]
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
#! /bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if type bazel > /dev/null; then
|
|
||||||
echo "Bazel has been installed already"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
apt update && apt install curl gnupg -y
|
|
||||||
curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg
|
|
||||||
mv bazel.gpg /etc/apt/trusted.gpg.d/
|
|
||||||
|
|
||||||
echo 'deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8' | tee /etc/apt/sources.list.d/bazel.list
|
|
||||||
apt update && apt install bazel=5.4.0 -y
|
|
||||||
|
|
||||||
echo "Bazel is installed successfully"
|
|
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "jinux-build"
|
name = "jinux-runner"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
# AUTOMATICALLY GENERATED FILE, DO NOT EDIT IF YOU KNOW WHAT YOU ARE DOING
|
# AUTOMATICALLY GENERATED FILE, DO NOT EDIT IF YOU KNOW WHAT YOU ARE DOING
|
||||||
|
|
||||||
# set debug=linux,efi
|
# set debug=linux,efi,relocator
|
||||||
|
|
||||||
set timeout_style=#GRUB_TIMEOUT_STYLE#
|
set timeout_style=#GRUB_TIMEOUT_STYLE#
|
||||||
set timeout=#GRUB_TIMEOUT#
|
set timeout=#GRUB_TIMEOUT#
|
||||||
|
|
||||||
menuentry 'jinux' {
|
menuentry 'jinux' {
|
||||||
#GRUB_CMD_KERNEL# /boot/#KERNEL_NAME# #KERNEL_COMMAND_LINE#
|
#GRUB_CMD_KERNEL# #KERNEL# #KERNEL_COMMAND_LINE#
|
||||||
#GRUB_CMD_INITRAMFS# /boot/initramfs.cpio.gz
|
#GRUB_CMD_INITRAMFS# /boot/initramfs.cpio.gz
|
||||||
boot
|
boot
|
||||||
}
|
}
|
2
runner/src/machine/mod.rs
Normal file
2
runner/src/machine/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod microvm;
|
||||||
|
pub mod qemu_grub_efi;
|
@ -4,9 +4,35 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::BootProtocol;
|
||||||
|
|
||||||
use glob::glob;
|
use glob::glob;
|
||||||
|
|
||||||
pub const MACHINE_ARGS: &[&str] = &["-machine", "q35,kernel-irqchip=split"];
|
macro_rules! ovmf_prefix {
|
||||||
|
() => {
|
||||||
|
// There are 3 optional OVMF builds at your service in the dev image
|
||||||
|
"/root/ovmf/release/"
|
||||||
|
// "/root/ovmf/debug/"
|
||||||
|
// "/usr/share/OVMF/"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const MACHINE_ARGS: &[&str] = &[
|
||||||
|
"-machine",
|
||||||
|
"q35,kernel-irqchip=split",
|
||||||
|
"-drive",
|
||||||
|
concat!(
|
||||||
|
"if=pflash,format=raw,unit=0,readonly=on,file=",
|
||||||
|
ovmf_prefix!(),
|
||||||
|
"OVMF_CODE.fd"
|
||||||
|
),
|
||||||
|
"-drive",
|
||||||
|
concat!(
|
||||||
|
"if=pflash,format=raw,unit=1,file=",
|
||||||
|
ovmf_prefix!(),
|
||||||
|
"OVMF_VARS.fd"
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
pub const NOIOMMU_DEVICE_ARGS: &[&str] = &[
|
pub const NOIOMMU_DEVICE_ARGS: &[&str] = &[
|
||||||
"-device",
|
"-device",
|
||||||
@ -30,121 +56,61 @@ pub const IOMMU_DEVICE_ARGS: &[&str] = &[
|
|||||||
"ioh3420,id=pcie.0,chassis=1",
|
"ioh3420,id=pcie.0,chassis=1",
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
pub const GRUB_LIB_PREFIX: &str = "/usr/lib/grub";
|
||||||
pub enum GrubBootProtocol {
|
pub const GRUB_VERSION: &str = "x86_64-efi";
|
||||||
Multiboot,
|
|
||||||
Multiboot2,
|
|
||||||
Linux,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_bootdev_image(
|
pub fn create_bootdev_image(
|
||||||
path: PathBuf,
|
jinux_path: PathBuf,
|
||||||
|
initramfs_path: PathBuf,
|
||||||
grub_cfg: String,
|
grub_cfg: String,
|
||||||
protocol: GrubBootProtocol,
|
protocol: BootProtocol,
|
||||||
) -> PathBuf {
|
) -> PathBuf {
|
||||||
let cwd = std::env::current_dir().unwrap();
|
let target_dir = jinux_path.parent().unwrap();
|
||||||
let target_dir = path.parent().unwrap();
|
let iso_root = target_dir.join("iso_root");
|
||||||
let out_dir = target_dir.join("boot_device");
|
|
||||||
|
|
||||||
// Clear or make the out dir.
|
// Clear or make the iso dir.
|
||||||
if out_dir.exists() {
|
if iso_root.exists() {
|
||||||
fs::remove_dir_all(&out_dir).unwrap();
|
fs::remove_dir_all(&iso_root).unwrap();
|
||||||
}
|
}
|
||||||
fs::create_dir_all(&out_dir).unwrap();
|
fs::create_dir_all(iso_root.join("boot").join("grub")).unwrap();
|
||||||
|
|
||||||
// Find the setup header in the build script output directory.
|
// Copy the initramfs to the boot directory.
|
||||||
let bs_out_dir = glob("target/x86_64-custom/debug/build/jinux-frame-*").unwrap();
|
fs::copy(
|
||||||
let header_bin = Path::new(bs_out_dir.into_iter().next().unwrap().unwrap().as_path())
|
initramfs_path,
|
||||||
.join("out")
|
iso_root.join("boot").join("initramfs.cpio.gz"),
|
||||||
.join("bin")
|
)
|
||||||
.join("jinux-frame-x86-boot-setup.bin");
|
.unwrap();
|
||||||
|
|
||||||
let target_path = match protocol {
|
let target_path = match protocol {
|
||||||
GrubBootProtocol::Linux => {
|
BootProtocol::Linux => {
|
||||||
|
// Find the setup header in the build script output directory.
|
||||||
|
let bs_out_dir = glob("target/x86_64-custom/debug/build/jinux-frame-*").unwrap();
|
||||||
|
let header_bin = Path::new(bs_out_dir.into_iter().next().unwrap().unwrap().as_path())
|
||||||
|
.join("out")
|
||||||
|
.join("bin")
|
||||||
|
.join("jinux-frame-x86-boot-setup.bin");
|
||||||
// Make the `zimage`-compatible kernel image and place it in the boot directory.
|
// Make the `zimage`-compatible kernel image and place it in the boot directory.
|
||||||
let target_path = out_dir.join("jinuz");
|
let target_path = iso_root.join("boot").join("jinuz");
|
||||||
make_zimage(&target_path, &path.as_path(), &header_bin.as_path()).unwrap();
|
make_zimage(&target_path, &jinux_path.as_path(), &header_bin.as_path()).unwrap();
|
||||||
|
target_path
|
||||||
|
}
|
||||||
|
BootProtocol::Multiboot | BootProtocol::Multiboot2 => {
|
||||||
|
// Copy the kernel image to the boot directory.
|
||||||
|
let target_path = iso_root.join("boot").join("jinux");
|
||||||
|
fs::copy(&jinux_path, &target_path).unwrap();
|
||||||
target_path
|
target_path
|
||||||
}
|
}
|
||||||
GrubBootProtocol::Multiboot | GrubBootProtocol::Multiboot2 => path.clone(),
|
|
||||||
};
|
};
|
||||||
let target_name = target_path.file_name().unwrap().to_str().unwrap();
|
let target_name = target_path.file_name().unwrap().to_str().unwrap();
|
||||||
|
|
||||||
// Write the grub.cfg file
|
// Write the grub.cfg file
|
||||||
let grub_cfg_path = out_dir.join("grub.cfg");
|
let grub_cfg_path = iso_root.join("boot").join("grub").join("grub.cfg");
|
||||||
fs::write(&grub_cfg_path, grub_cfg).unwrap();
|
fs::write(&grub_cfg_path, grub_cfg).unwrap();
|
||||||
|
|
||||||
// Make the boot device CDROM image.
|
// Make the boot device CDROM image.
|
||||||
|
let iso_path = target_dir.join(target_name.to_string() + ".iso");
|
||||||
// Firstly use `grub-mkrescue` to generate grub.img.
|
let mut cmd = std::process::Command::new("grub-mkrescue");
|
||||||
let grub_img_path = out_dir.join("grub.img");
|
cmd.arg("--output").arg(&iso_path).arg(iso_root.as_os_str());
|
||||||
let mut cmd = std::process::Command::new("grub-mkimage");
|
|
||||||
cmd.arg("--format=i386-pc")
|
|
||||||
.arg(format!("--prefix={}", out_dir.display()))
|
|
||||||
.arg(format!("--output={}", grub_img_path.display()));
|
|
||||||
// A embedded config file should be used to find the real config with menuentries.
|
|
||||||
cmd.arg("--config=build/grub/grub.cfg.embedded");
|
|
||||||
let grub_modules = &[
|
|
||||||
"linux",
|
|
||||||
"boot",
|
|
||||||
"multiboot",
|
|
||||||
"multiboot2",
|
|
||||||
"elf",
|
|
||||||
"loadenv",
|
|
||||||
"memdisk",
|
|
||||||
"biosdisk",
|
|
||||||
"iso9660",
|
|
||||||
"normal",
|
|
||||||
"loopback",
|
|
||||||
"chain",
|
|
||||||
"configfile",
|
|
||||||
"halt",
|
|
||||||
"help",
|
|
||||||
"ls",
|
|
||||||
"reboot",
|
|
||||||
"echo",
|
|
||||||
"test",
|
|
||||||
"sleep",
|
|
||||||
"true",
|
|
||||||
"vbe",
|
|
||||||
"vga",
|
|
||||||
"video_bochs",
|
|
||||||
];
|
|
||||||
for module in grub_modules {
|
|
||||||
cmd.arg(module);
|
|
||||||
}
|
|
||||||
if !cmd.status().unwrap().success() {
|
|
||||||
panic!("Failed to run `{:?}`.", cmd);
|
|
||||||
}
|
|
||||||
// Secondly prepend grub.img with cdboot.img.
|
|
||||||
let cdboot_path = PathBuf::from("/usr/lib/grub/i386-pc/cdboot.img");
|
|
||||||
let mut grub_img = fs::read(cdboot_path).unwrap();
|
|
||||||
grub_img.append(&mut fs::read(&grub_img_path).unwrap());
|
|
||||||
fs::write(&grub_img_path, &grub_img).unwrap();
|
|
||||||
|
|
||||||
// Finally use the `genisoimage` command to generate the CDROM image.
|
|
||||||
let iso_path = out_dir.join(target_name.to_string() + ".iso");
|
|
||||||
let mut cmd = std::process::Command::new("genisoimage");
|
|
||||||
cmd.arg("-graft-points")
|
|
||||||
.arg("-quiet")
|
|
||||||
.arg("-R")
|
|
||||||
.arg("-no-emul-boot")
|
|
||||||
.arg("-boot-info-table")
|
|
||||||
.arg("-boot-load-size")
|
|
||||||
.arg("4")
|
|
||||||
.arg("-input-charset")
|
|
||||||
.arg("utf8")
|
|
||||||
.arg("-A")
|
|
||||||
.arg("jinux-grub2")
|
|
||||||
.arg("-b")
|
|
||||||
.arg(&grub_img_path)
|
|
||||||
.arg("-o")
|
|
||||||
.arg(&iso_path)
|
|
||||||
.arg(format!("boot/{}={}", target_name, target_path.display()))
|
|
||||||
.arg(format!("boot/grub/grub.cfg={}", grub_cfg_path.display()))
|
|
||||||
.arg(format!("boot/grub/grub.img={}", grub_img_path.display()))
|
|
||||||
.arg("boot/initramfs.cpio.gz=regression/build/initramfs.cpio.gz")
|
|
||||||
.arg(cwd.as_os_str());
|
|
||||||
if !cmd.status().unwrap().success() {
|
if !cmd.status().unwrap().success() {
|
||||||
panic!("Failed to run `{:?}`.", cmd);
|
panic!("Failed to run `{:?}`.", cmd);
|
||||||
}
|
}
|
||||||
@ -156,7 +122,7 @@ pub fn generate_grub_cfg(
|
|||||||
template_filename: &str,
|
template_filename: &str,
|
||||||
kcmdline: &str,
|
kcmdline: &str,
|
||||||
skip_grub_menu: bool,
|
skip_grub_menu: bool,
|
||||||
protocol: GrubBootProtocol,
|
protocol: BootProtocol,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
|
|
||||||
@ -166,7 +132,7 @@ pub fn generate_grub_cfg(
|
|||||||
.read_to_string(&mut buffer)
|
.read_to_string(&mut buffer)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Delete the first two lines that notes the file is a template file.
|
// Delete the first two lines that notes the file a template file.
|
||||||
let buffer = buffer.lines().skip(2).collect::<Vec<&str>>().join("\n");
|
let buffer = buffer.lines().skip(2).collect::<Vec<&str>>().join("\n");
|
||||||
// Set the timout style and timeout.
|
// Set the timout style and timeout.
|
||||||
let buffer = buffer
|
let buffer = buffer
|
||||||
@ -179,23 +145,28 @@ pub fn generate_grub_cfg(
|
|||||||
let buffer = buffer.replace("#KERNEL_COMMAND_LINE#", kcmdline);
|
let buffer = buffer.replace("#KERNEL_COMMAND_LINE#", kcmdline);
|
||||||
// Replace the grub commands according to the protocol selected.
|
// Replace the grub commands according to the protocol selected.
|
||||||
let buffer = match protocol {
|
let buffer = match protocol {
|
||||||
GrubBootProtocol::Multiboot => buffer
|
BootProtocol::Multiboot => buffer
|
||||||
.replace("#GRUB_CMD_KERNEL#", "multiboot")
|
.replace("#GRUB_CMD_KERNEL#", "multiboot")
|
||||||
.replace("#KERNEL_NAME#", "jinux")
|
.replace("#KERNEL#", "/boot/jinux")
|
||||||
.replace("#GRUB_CMD_INITRAMFS#", "module --nounzip"),
|
.replace("#GRUB_CMD_INITRAMFS#", "module --nounzip"),
|
||||||
GrubBootProtocol::Multiboot2 => buffer
|
BootProtocol::Multiboot2 => buffer
|
||||||
.replace("#GRUB_CMD_KERNEL#", "multiboot2")
|
.replace("#GRUB_CMD_KERNEL#", "multiboot2")
|
||||||
.replace("#KERNEL_NAME#", "jinux")
|
.replace("#KERNEL#", "/boot/jinux")
|
||||||
.replace("#GRUB_CMD_INITRAMFS#", "module2 --nounzip"),
|
.replace("#GRUB_CMD_INITRAMFS#", "module2 --nounzip"),
|
||||||
GrubBootProtocol::Linux => buffer
|
BootProtocol::Linux => buffer
|
||||||
.replace("#GRUB_CMD_KERNEL#", "linux")
|
.replace("#GRUB_CMD_KERNEL#", "linux")
|
||||||
.replace("#KERNEL_NAME#", "jinuz")
|
.replace("#KERNEL#", "/boot/jinuz")
|
||||||
.replace("#GRUB_CMD_INITRAMFS#", "initrd"),
|
.replace("#GRUB_CMD_INITRAMFS#", "initrd"),
|
||||||
};
|
};
|
||||||
|
|
||||||
buffer
|
buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This function sould be used when generating the Linux x86 Boot setup header.
|
||||||
|
/// Some fields in the Linux x86 Boot setup header should be filled after assembled.
|
||||||
|
/// And the filled fields must have the bytes with values of 0xAB. See
|
||||||
|
/// `framework/jinux-frame/src/arch/x86/boot/linux_boot/setup/src/header.S` for more
|
||||||
|
/// info on this mechanism.
|
||||||
fn fill_header_field(header: &mut [u8], offset: usize, value: &[u8]) {
|
fn fill_header_field(header: &mut [u8], offset: usize, value: &[u8]) {
|
||||||
let size = value.len();
|
let size = value.len();
|
||||||
assert_eq!(
|
assert_eq!(
|
@ -5,8 +5,9 @@
|
|||||||
//! The runner will generate the filesystem image for starting Jinux. If
|
//! The runner will generate the filesystem image for starting Jinux. If
|
||||||
//! we should use the runner in the default mode, which invokes QEMU with
|
//! we should use the runner in the default mode, which invokes QEMU with
|
||||||
//! a GRUB boot device image, the runner would be responsible for generating
|
//! a GRUB boot device image, the runner would be responsible for generating
|
||||||
//! the and the boot device image. It also supports directly boot the
|
//! the appropriate kernel image and the boot device image. It also supports
|
||||||
//! kernel image without GRUB using the QEMU microvm mode.
|
//! to directly boot the kernel image without GRUB using the QEMU microvm
|
||||||
|
//! machine type.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
pub mod machine;
|
pub mod machine;
|
||||||
@ -18,10 +19,22 @@ use std::{
|
|||||||
process::Command,
|
process::Command,
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::{Parser, ValueEnum};
|
||||||
|
|
||||||
use crate::machine::{default, microvm};
|
use crate::machine::{microvm, qemu_grub_efi};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, ValueEnum)]
|
||||||
|
enum BootMethod {
|
||||||
|
QemuGrub,
|
||||||
|
Microvm,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, ValueEnum)]
|
||||||
|
pub enum BootProtocol {
|
||||||
|
Multiboot,
|
||||||
|
Multiboot2,
|
||||||
|
Linux,
|
||||||
|
}
|
||||||
/// The CLI of this runner.
|
/// The CLI of this runner.
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
@ -36,12 +49,17 @@ struct Args {
|
|||||||
|
|
||||||
// Optional arguments.
|
// Optional arguments.
|
||||||
/// Boot method. Can be one of the following items:
|
/// Boot method. Can be one of the following items:
|
||||||
/// - `grub-multiboot`,
|
/// - `qemu-grub`;
|
||||||
/// - `grub-multiboot2`,
|
/// - `microvm`.
|
||||||
/// - `grub-linux`,
|
#[arg(long, value_enum, default_value_t = BootMethod::QemuGrub)]
|
||||||
/// - `microvm-multiboot`.
|
boot_method: BootMethod,
|
||||||
#[arg(long, default_value = "grub-multiboot2")]
|
|
||||||
boot_method: String,
|
/// Boot protocol. Can be one of the following items:
|
||||||
|
/// - `multiboot`;
|
||||||
|
/// - `multiboot2`;
|
||||||
|
/// - `linux`.
|
||||||
|
#[arg(long, value_enum, default_value_t = BootProtocol::Multiboot2)]
|
||||||
|
boot_protocol: BootProtocol,
|
||||||
|
|
||||||
/// Enable KVM when running QEMU.
|
/// Enable KVM when running QEMU.
|
||||||
#[arg(long, default_value_t = false)]
|
#[arg(long, default_value_t = false)]
|
||||||
@ -83,15 +101,12 @@ pub const COMMON_ARGS: &[&str] = &[
|
|||||||
"filter-dump,id=filter0,netdev=net01,file=virtio-net.pcap",
|
"filter-dump,id=filter0,netdev=net01,file=virtio-net.pcap",
|
||||||
];
|
];
|
||||||
|
|
||||||
pub fn random_hostfwd_netdev_arg() -> String {
|
pub fn random_hostfwd_ports() -> (u16, u16) {
|
||||||
let start = 32768u16;
|
let start = 32768u16;
|
||||||
let end = 61000u16;
|
let end = 61000u16;
|
||||||
let port1 = rand::random::<u16>() % (end - 1 - start) + start;
|
let port1 = rand::random::<u16>() % (end - 1 - start) + start;
|
||||||
let port2 = rand::random::<u16>() % (end - port1) + port1;
|
let port2 = rand::random::<u16>() % (end - port1) + port1;
|
||||||
format!(
|
(port1, port2)
|
||||||
"user,id=net01,hostfwd=tcp::{}-:22,hostfwd=tcp::{}-:8080",
|
|
||||||
port1, port2
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const GDB_ARGS: &[&str] = &[
|
pub const GDB_ARGS: &[&str] = &[
|
||||||
@ -109,12 +124,13 @@ fn run_gdb_client(path: &PathBuf, gdb_grub: bool) {
|
|||||||
gdb_cmd.arg("-ex").arg("set arch i386:x86-64:intel");
|
gdb_cmd.arg("-ex").arg("set arch i386:x86-64:intel");
|
||||||
let grub_script = "/tmp/jinux-gdb-grub-script";
|
let grub_script = "/tmp/jinux-gdb-grub-script";
|
||||||
if gdb_grub {
|
if gdb_grub {
|
||||||
|
let grub_dir =
|
||||||
|
PathBuf::from(qemu_grub_efi::GRUB_LIB_PREFIX).join(qemu_grub_efi::GRUB_VERSION);
|
||||||
// Load symbols from GRUB using the provided grub gdb script.
|
// Load symbols from GRUB using the provided grub gdb script.
|
||||||
// Read the contents from /usr/lib/grub/i386-pc/gdb_grub and
|
// Read the contents from `gdb_grub` and
|
||||||
// replace the lines containing "file kernel.exec" and
|
// replace the lines containing "target remote :1234".
|
||||||
// "target remote :1234".
|
gdb_cmd.current_dir(&grub_dir);
|
||||||
gdb_cmd.current_dir("/usr/lib/grub/i386-pc/");
|
let grub_script_content = std::fs::read_to_string(grub_dir.join("gdb_grub")).unwrap();
|
||||||
let grub_script_content = include_str!("/usr/lib/grub/i386-pc/gdb_grub");
|
|
||||||
let lines = grub_script_content.lines().collect::<Vec<_>>();
|
let lines = grub_script_content.lines().collect::<Vec<_>>();
|
||||||
let mut f = OpenOptions::new()
|
let mut f = OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
@ -122,7 +138,13 @@ fn run_gdb_client(path: &PathBuf, gdb_grub: bool) {
|
|||||||
.open(grub_script)
|
.open(grub_script)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for line in lines {
|
for line in lines {
|
||||||
if line.contains("target remote :1234") {
|
if line.contains("file kernel.exec") {
|
||||||
|
writeln!(f, "{}", line).unwrap();
|
||||||
|
// A horrible hack on GRUB EFI debugging.
|
||||||
|
// https://stackoverflow.com/questions/43872078/debug-grub2-efi-image-running-on-qemu
|
||||||
|
// Please use our custom built debug OVMF image to confirm the entrypoint address.
|
||||||
|
writeln!(f, "add-symbol-file kernel.exec 0x0007E69F000").unwrap();
|
||||||
|
} else if line.contains("target remote :1234") {
|
||||||
// Connect to the GDB server.
|
// Connect to the GDB server.
|
||||||
writeln!(f, "target remote /tmp/jinux-gdb-socket").unwrap();
|
writeln!(f, "target remote /tmp/jinux-gdb-socket").unwrap();
|
||||||
} else {
|
} else {
|
||||||
@ -151,10 +173,10 @@ fn main() {
|
|||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
if args.run_gdb_client {
|
if args.run_gdb_client {
|
||||||
let gdb_grub = args.boot_method.contains("grub");
|
let gdb_grub = args.boot_method == BootMethod::QemuGrub;
|
||||||
// You should comment out this code if you want to debug gdb instead
|
// You should comment out the next line if you want to debug grub instead
|
||||||
// of the kernel because this argument is not exposed by runner CLI.
|
// of the kernel because this argument is not exposed by runner CLI.
|
||||||
// let gdb_grub = gdb_grub && false;
|
let gdb_grub = gdb_grub && false;
|
||||||
run_gdb_client(&args.path, gdb_grub);
|
run_gdb_client(&args.path, gdb_grub);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -164,11 +186,19 @@ fn main() {
|
|||||||
qemu_cmd.args(COMMON_ARGS);
|
qemu_cmd.args(COMMON_ARGS);
|
||||||
|
|
||||||
qemu_cmd.arg("-netdev");
|
qemu_cmd.arg("-netdev");
|
||||||
qemu_cmd.arg(random_hostfwd_netdev_arg().as_str());
|
let (port1, port2) = random_hostfwd_ports();
|
||||||
|
qemu_cmd.arg(format!(
|
||||||
|
"user,id=net01,hostfwd=tcp::{}-:22,hostfwd=tcp::{}-:8080",
|
||||||
|
port1, port2
|
||||||
|
));
|
||||||
|
println!(
|
||||||
|
"[jinux-runner] Binding host ports to guest ports: ({} -> {}); ({} -> {}).",
|
||||||
|
port1, 22, port2, 8080
|
||||||
|
);
|
||||||
|
|
||||||
if args.halt_for_gdb {
|
if args.halt_for_gdb {
|
||||||
if args.enable_kvm {
|
if args.enable_kvm {
|
||||||
println!("Runner: Can't enable KVM when running QEMU as a GDB server. Abort.");
|
println!("[jinux-runner] Can't enable KVM when running QEMU as a GDB server. Abort.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qemu_cmd.args(GDB_ARGS);
|
qemu_cmd.args(GDB_ARGS);
|
||||||
@ -177,26 +207,26 @@ fn main() {
|
|||||||
if args.enable_kvm {
|
if args.enable_kvm {
|
||||||
qemu_cmd.arg("-enable-kvm");
|
qemu_cmd.arg("-enable-kvm");
|
||||||
}
|
}
|
||||||
// Specify machine type
|
// Add machine-specific arguments
|
||||||
if args.boot_method == "microvm-multiboot" {
|
if args.boot_method == BootMethod::QemuGrub {
|
||||||
|
qemu_cmd.args(qemu_grub_efi::MACHINE_ARGS);
|
||||||
|
} else if args.boot_method == BootMethod::Microvm {
|
||||||
qemu_cmd.args(microvm::MACHINE_ARGS);
|
qemu_cmd.args(microvm::MACHINE_ARGS);
|
||||||
} else {
|
|
||||||
qemu_cmd.args(default::MACHINE_ARGS);
|
|
||||||
}
|
}
|
||||||
// Add device arguments
|
// Add device arguments
|
||||||
if args.boot_method == "microvm-multiboot" {
|
if args.boot_method == BootMethod::Microvm {
|
||||||
qemu_cmd.args(microvm::DEVICE_ARGS);
|
qemu_cmd.args(microvm::DEVICE_ARGS);
|
||||||
} else if args.emulate_iommu {
|
} else if args.emulate_iommu {
|
||||||
qemu_cmd.args(default::IOMMU_DEVICE_ARGS);
|
qemu_cmd.args(qemu_grub_efi::IOMMU_DEVICE_ARGS);
|
||||||
} else {
|
} else {
|
||||||
qemu_cmd.args(default::NOIOMMU_DEVICE_ARGS);
|
qemu_cmd.args(qemu_grub_efi::NOIOMMU_DEVICE_ARGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fs_image = create_fs_image(args.path.as_path());
|
let fs_image = create_fs_image(args.path.as_path());
|
||||||
qemu_cmd.arg("-drive");
|
qemu_cmd.arg("-drive");
|
||||||
qemu_cmd.arg(fs_image);
|
qemu_cmd.arg(fs_image);
|
||||||
|
|
||||||
if args.boot_method == "microvm-multiboot" {
|
if args.boot_method == BootMethod::Microvm {
|
||||||
let image = microvm::create_bootdev_image(args.path);
|
let image = microvm::create_bootdev_image(args.path);
|
||||||
qemu_cmd.arg("-kernel");
|
qemu_cmd.arg("-kernel");
|
||||||
qemu_cmd.arg(image.as_os_str());
|
qemu_cmd.arg(image.as_os_str());
|
||||||
@ -204,25 +234,25 @@ fn main() {
|
|||||||
qemu_cmd.arg(&args.kcmdline);
|
qemu_cmd.arg(&args.kcmdline);
|
||||||
qemu_cmd.arg("-initrd");
|
qemu_cmd.arg("-initrd");
|
||||||
qemu_cmd.arg("regression/build/initramfs.cpio.gz");
|
qemu_cmd.arg("regression/build/initramfs.cpio.gz");
|
||||||
} else {
|
} else if args.boot_method == BootMethod::QemuGrub {
|
||||||
let boot_protocol = match args.boot_method.as_str() {
|
let grub_cfg = qemu_grub_efi::generate_grub_cfg(
|
||||||
"grub-multiboot" => default::GrubBootProtocol::Multiboot,
|
"runner/grub/grub.cfg.template",
|
||||||
"grub-multiboot2" => default::GrubBootProtocol::Multiboot2,
|
|
||||||
"grub-linux" => default::GrubBootProtocol::Linux,
|
|
||||||
_ => panic!("Unknown boot method: {}", args.boot_method),
|
|
||||||
};
|
|
||||||
let grub_cfg = default::generate_grub_cfg(
|
|
||||||
"build/grub/grub.cfg.template",
|
|
||||||
&args.kcmdline,
|
&args.kcmdline,
|
||||||
args.skip_grub_menu,
|
args.skip_grub_menu,
|
||||||
boot_protocol,
|
args.boot_protocol,
|
||||||
|
);
|
||||||
|
let initramfs_path = PathBuf::from("regression/build/initramfs.cpio.gz");
|
||||||
|
let bootdev_image = qemu_grub_efi::create_bootdev_image(
|
||||||
|
args.path,
|
||||||
|
initramfs_path,
|
||||||
|
grub_cfg,
|
||||||
|
args.boot_protocol,
|
||||||
);
|
);
|
||||||
let bootdev_image = default::create_bootdev_image(args.path, grub_cfg, boot_protocol);
|
|
||||||
qemu_cmd.arg("-cdrom");
|
qemu_cmd.arg("-cdrom");
|
||||||
qemu_cmd.arg(bootdev_image.as_os_str());
|
qemu_cmd.arg(bootdev_image.as_os_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("running:{:#?}", qemu_cmd);
|
println!("[jinux-runner] Running: {:#?}", qemu_cmd);
|
||||||
|
|
||||||
let exit_status = qemu_cmd.status().unwrap();
|
let exit_status = qemu_cmd.status().unwrap();
|
||||||
if !exit_status.success() {
|
if !exit_status.success() {
|
@ -24,7 +24,7 @@ static CARGO_COMPONENT_PATH: LazyLock<PathBuf> = LazyLock::new(|| {
|
|||||||
});
|
});
|
||||||
|
|
||||||
pub fn run_cargo_component(test_name: &str) -> String {
|
pub fn run_cargo_component(test_name: &str) -> String {
|
||||||
let root_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
let target_dir = root_dir.join("target").join(test_name);
|
let target_dir = root_dir.join("target").join(test_name);
|
||||||
let cwd = root_dir.join("tests").join(test_name);
|
let cwd = root_dir.join("tests").join(test_name);
|
||||||
let output = cargo_clean(&cwd, &target_dir);
|
let output = cargo_clean(&cwd, &target_dir);
|
||||||
|
@ -199,7 +199,7 @@ fn calculate_priority(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn metadata() -> json::JsonValue {
|
fn metadata() -> json::JsonValue {
|
||||||
let mut cmd = Command::new(std::env::var("CARGO").unwrap());
|
let mut cmd = Command::new(env!("CARGO"));
|
||||||
cmd.arg("metadata");
|
cmd.arg("metadata");
|
||||||
cmd.arg("--format-version").arg("1");
|
cmd.arg("--format-version").arg("1");
|
||||||
let output = cmd.output().unwrap();
|
let output = cmd.output().unwrap();
|
||||||
|
@ -1,25 +1,34 @@
|
|||||||
FROM ubuntu:22.04 as ubuntu-22.04-with-bazel
|
FROM ubuntu:22.04 as build-base
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-c"]
|
SHELL ["/bin/bash", "-c"]
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
# Install all Bazel dependent packages
|
|
||||||
RUN apt update && apt-get install -y --no-install-recommends \
|
RUN apt update && apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
curl \
|
curl \
|
||||||
git-core \
|
git-core \
|
||||||
gnupg \
|
libssl-dev \
|
||||||
python-is-python3 \
|
python-is-python3 \
|
||||||
python3-pip
|
python3-pip \
|
||||||
|
wget \
|
||||||
|
gnupg
|
||||||
|
|
||||||
|
#= Build syscall test =========================================================
|
||||||
|
|
||||||
|
FROM build-base as build-bazel
|
||||||
|
|
||||||
# Install bazel, which is required by the system call test suite from Gvisor project
|
# Install bazel, which is required by the system call test suite from Gvisor project
|
||||||
COPY regression/syscall_test/install_bazel.sh /tmp/
|
WORKDIR /root/bazel
|
||||||
WORKDIR /tmp
|
RUN curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg
|
||||||
RUN ./install_bazel.sh && rm -f /tmp/install_bazel.sh
|
RUN mv bazel.gpg /etc/apt/trusted.gpg.d
|
||||||
|
RUN echo 'deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8' | tee /etc/apt/sources.list.d/bazel.list
|
||||||
|
RUN apt update && apt install bazel=5.4.0 -y
|
||||||
|
RUN apt clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
WORKDIR /root
|
||||||
|
RUN rm -rf bazel
|
||||||
|
|
||||||
FROM ubuntu-22.04-with-bazel as syscall_test
|
FROM build-bazel as syscall_test
|
||||||
|
|
||||||
# Build the syscall test binaries
|
# Build the syscall test binaries
|
||||||
COPY regression/syscall_test /root/syscall_test
|
COPY regression/syscall_test /root/syscall_test
|
||||||
@ -27,38 +36,110 @@ WORKDIR /root/syscall_test
|
|||||||
RUN export BUILD_DIR=build && \
|
RUN export BUILD_DIR=build && \
|
||||||
make ${BUILD_DIR}/syscall_test_bins
|
make ${BUILD_DIR}/syscall_test_bins
|
||||||
|
|
||||||
FROM ubuntu-22.04-with-bazel
|
#= Build QEMU =================================================================
|
||||||
|
|
||||||
|
FROM build-base as build-qemu
|
||||||
|
|
||||||
# Install all Jinux dependent packages
|
|
||||||
RUN apt update && apt-get install -y --no-install-recommends \
|
RUN apt update && apt-get install -y --no-install-recommends \
|
||||||
cpio \
|
libgcrypt-dev `# optional build dependency` \
|
||||||
cpuid \
|
libglib2.0-dev `# build dependency` \
|
||||||
file \
|
libpixman-1-dev `# build dependency` \
|
||||||
g++ \
|
libusb-dev `# optional build dependency` \
|
||||||
gdb \
|
meson \
|
||||||
grub-common \
|
ninja-build
|
||||||
grub-pc \
|
RUN apt clean && rm -rf /var/lib/apt/lists/*
|
||||||
grub-pc-dbg \
|
|
||||||
libssl-dev \
|
|
||||||
net-tools \
|
|
||||||
openssh-server \
|
|
||||||
pkg-config \
|
|
||||||
qemu-system-x86 \
|
|
||||||
strace \
|
|
||||||
sudo \
|
|
||||||
unzip \
|
|
||||||
vim \
|
|
||||||
wget \
|
|
||||||
xorriso \
|
|
||||||
zip
|
|
||||||
|
|
||||||
# Clean apt cache
|
FROM build-qemu as qemu
|
||||||
RUN apt clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Prepare the system call test suite
|
# Fetch and install QEMU from https://download.qemu.org/qemu-8.1.1.tar.xz
|
||||||
COPY --from=syscall_test /root/syscall_test/build/syscall_test_bins /root/syscall_test_bins
|
#
|
||||||
ENV JINUX_PREBUILT_SYSCALL_TEST=/root/syscall_test_bins
|
# The QEMU version in the Ubuntu 22.04 repository is 6.*, which has a bug to cause OVMF debug to fail.
|
||||||
|
# The libslirp dependency is for QEMU's network backend.
|
||||||
|
WORKDIR /root
|
||||||
|
RUN wget -O qemu.tar.xz https://download.qemu.org/qemu-8.1.1.tar.xz \
|
||||||
|
&& mkdir /root/qemu \
|
||||||
|
&& tar xf qemu.tar.xz --strip-components=1 -C /root/qemu \
|
||||||
|
&& rm qemu.tar.xz
|
||||||
|
WORKDIR /root/qemu
|
||||||
|
RUN ./configure --target-list=x86_64-softmmu --prefix=/usr/local/qemu --enable-slirp \
|
||||||
|
&& make -j \
|
||||||
|
&& make install
|
||||||
|
WORKDIR /root
|
||||||
|
RUN rm -rf /root/qemu
|
||||||
|
|
||||||
|
#= Build OVMF =================================================================
|
||||||
|
|
||||||
|
FROM build-base as build-ovmf
|
||||||
|
|
||||||
|
RUN apt update && apt-get install -y --no-install-recommends \
|
||||||
|
bison \
|
||||||
|
flex \
|
||||||
|
iasl \
|
||||||
|
nasm \
|
||||||
|
uuid-dev
|
||||||
|
RUN apt clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
FROM build-ovmf as ovmf
|
||||||
|
|
||||||
|
# Fetch and build OVMF from the EDK2 official source
|
||||||
|
WORKDIR /root
|
||||||
|
RUN git clone --depth 1 --branch edk2-stable202308 --recurse-submodules --shallow-submodules https://github.com/tianocore/edk2.git
|
||||||
|
WORKDIR /root/edk2
|
||||||
|
RUN source ./edksetup.sh \
|
||||||
|
&& make -C BaseTools \
|
||||||
|
&& build -a X64 -t GCC5 -b DEBUG -p OvmfPkg/OvmfPkgX64.dsc -D DEBUG_ON_SERIAL_PORT \
|
||||||
|
&& build -a X64 -t GCC5 -b RELEASE -p OvmfPkg/OvmfPkgX64.dsc
|
||||||
|
|
||||||
|
#= Build GRUB =================================================================
|
||||||
|
|
||||||
|
FROM build-base as build-grub
|
||||||
|
|
||||||
|
RUN apt update && apt-get install -y --no-install-recommends \
|
||||||
|
bison \
|
||||||
|
flex
|
||||||
|
RUN apt clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
FROM build-grub as grub
|
||||||
|
|
||||||
|
# Fetch and install GRUB from the GNU official source
|
||||||
|
#
|
||||||
|
# We have installed grub-efi-amd64-bin just for the unicode.pf2 file, which is not included
|
||||||
|
# in the GRUB release. The Ubuntu release notoriously modifies the GRUB source code and enforce
|
||||||
|
# EFI handover boot, which is deprecated. So we have to build GRUB from source.
|
||||||
|
WORKDIR /root
|
||||||
|
RUN wget -O grub.tar.xz https://ftp.gnu.org/gnu/grub/grub-2.06.tar.xz \
|
||||||
|
&& mkdir /root/grub \
|
||||||
|
&& tar xf grub.tar.xz --strip-components=1 -C /root/grub \
|
||||||
|
&& rm grub.tar.xz
|
||||||
|
WORKDIR /root/grub
|
||||||
|
RUN ./configure --target=x86_64 --with-platform=efi --prefix=/usr/local/grub \
|
||||||
|
&& make -j \
|
||||||
|
&& make install
|
||||||
|
WORKDIR /root
|
||||||
|
RUN rm -rf /root/grub
|
||||||
|
|
||||||
|
#= Build busybox ==============================================================
|
||||||
|
|
||||||
|
FROM build-base as build-busybox
|
||||||
|
|
||||||
|
RUN apt clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
FROM build-busybox as busybox
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
RUN wget -O busybox.tar.bz2 https://busybox.net/downloads/busybox-1.35.0.tar.bz2 \
|
||||||
|
&& mkdir /root/busybox \
|
||||||
|
&& tar xf busybox.tar.bz2 --strip-components=1 -C /root/busybox \
|
||||||
|
&& rm busybox.tar.bz2
|
||||||
|
WORKDIR /root/busybox
|
||||||
|
RUN make defconfig \
|
||||||
|
&& sed -i "s/# CONFIG_STATIC is not set/CONFIG_STATIC=y/g" .config \
|
||||||
|
&& sed -i "s/# CONFIG_FEATURE_SH_STANDALONE is not set/CONFIG_FEATURE_SH_STANDALONE=y/g" .config \
|
||||||
|
&& make -j
|
||||||
|
|
||||||
|
#= The final stages to produce the Jinux development image ====================
|
||||||
|
|
||||||
|
FROM build-base as rust
|
||||||
|
|
||||||
# Install Rust
|
# Install Rust
|
||||||
ENV PATH="/root/.cargo/bin:${PATH}"
|
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||||
@ -70,24 +151,59 @@ RUN curl https://sh.rustup.rs -sSf | \
|
|||||||
&& rustup component add rust-src rustc-dev llvm-tools-preview
|
&& rustup component add rust-src rustc-dev llvm-tools-preview
|
||||||
|
|
||||||
# Install cargo tools
|
# Install cargo tools
|
||||||
RUN cargo install mdbook \
|
RUN cargo install \
|
||||||
&& cargo install cargo-binutils
|
cargo-binutils \
|
||||||
|
mdbook
|
||||||
|
|
||||||
|
FROM rust
|
||||||
|
|
||||||
|
# Install all Jinux dependent packages
|
||||||
|
RUN apt update && apt-get install -y --no-install-recommends \
|
||||||
|
cpio \
|
||||||
|
cpuid \
|
||||||
|
file \
|
||||||
|
gdb \
|
||||||
|
grub-efi-amd64-bin \
|
||||||
|
libpixman-1-dev `# running dependency for QEMU` \
|
||||||
|
mtools `# used by grub-mkrescue` \
|
||||||
|
net-tools \
|
||||||
|
openssh-server \
|
||||||
|
ovmf `# provide an alternative stable firmware`\
|
||||||
|
pkg-config \
|
||||||
|
strace \
|
||||||
|
sudo \
|
||||||
|
unzip \
|
||||||
|
vim \
|
||||||
|
xorriso \
|
||||||
|
zip
|
||||||
|
# Clean apt cache
|
||||||
|
RUN apt clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Prepare the system call test suite
|
||||||
|
COPY --from=syscall_test /root/syscall_test/build/syscall_test_bins /root/syscall_test_bins
|
||||||
|
ENV JINUX_PREBUILT_SYSCALL_TEST=/root/syscall_test_bins
|
||||||
|
|
||||||
|
# Install QEMU built from the previous stages
|
||||||
|
COPY --from=qemu /usr/local/qemu /usr/local/qemu
|
||||||
|
ENV PATH="/usr/local/qemu/bin:${PATH}"
|
||||||
|
ENV LD_LIBRARY_PATH="/usr/local/qemu/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}"
|
||||||
|
|
||||||
|
# Install OVMF built from the previous stages
|
||||||
|
COPY --from=ovmf /root/edk2/Build/OvmfX64/DEBUG_GCC5/FV/ /root/ovmf/debug
|
||||||
|
COPY --from=ovmf /root/edk2/Build/OvmfX64/RELEASE_GCC5/FV/ /root/ovmf/release
|
||||||
|
|
||||||
|
# Install GRUB built from the previous stages
|
||||||
|
COPY --from=grub /usr/local/grub /usr/local/grub
|
||||||
|
ENV PATH="/usr/local/grub/bin:${PATH}"
|
||||||
|
# Make a symbolic link for `unicode.pf2` from Ubuntu 22.04 package
|
||||||
|
RUN ln -sf /usr/share/grub/unicode.pf2 /usr/local/grub/share/grub/unicode.pf2
|
||||||
|
|
||||||
|
# Install Busybox built from the previous stages
|
||||||
|
COPY --from=busybox /root/busybox/busybox /bin/busybox
|
||||||
|
|
||||||
# Add the path of jinux tools
|
# Add the path of jinux tools
|
||||||
ENV PATH="/root/jinux/target/bin:${PATH}"
|
ENV PATH="/root/jinux/target/bin:${PATH}"
|
||||||
|
|
||||||
# Build busybox
|
|
||||||
RUN curl --output busybox.tar.bz2 https://busybox.net/downloads/busybox-1.35.0.tar.bz2 \
|
|
||||||
&& mkdir /root/busybox \
|
|
||||||
&& tar xf busybox.tar.bz2 --strip-components=1 -C /root/busybox \
|
|
||||||
&& rm busybox.tar.bz2
|
|
||||||
WORKDIR /root/busybox
|
|
||||||
RUN make defconfig \
|
|
||||||
&& sed -i "s/# CONFIG_STATIC is not set/CONFIG_STATIC=y/g" .config \
|
|
||||||
&& sed -i "s/# CONFIG_FEATURE_SH_STANDALONE is not set/CONFIG_FEATURE_SH_STANDALONE=y/g" .config \
|
|
||||||
&& make -j \
|
|
||||||
&& cp /root/busybox/busybox /bin/busybox
|
|
||||||
|
|
||||||
VOLUME [ "/root/jinux" ]
|
VOLUME [ "/root/jinux" ]
|
||||||
|
|
||||||
WORKDIR /root/jinux
|
WORKDIR /root/jinux
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"llvm-target": "x86_64-unknown-none",
|
"llvm-target": "x86_64-unknown-none",
|
||||||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
|
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
|
||||||
"code-model": "kernel",
|
"code-model": "kernel",
|
||||||
"cpu": "x86-64",
|
"cpu": "x86-64",
|
||||||
"arch": "x86_64",
|
"arch": "x86_64",
|
||||||
"target-endian": "little",
|
"target-endian": "little",
|
||||||
"target-pointer-width": "64",
|
"target-pointer-width": "64",
|
||||||
"target-c-int-width": "32",
|
"target-c-int-width": "32",
|
||||||
"os": "none",
|
"os": "none",
|
||||||
"executables": true,
|
"executables": true,
|
||||||
"linker-flavor": "ld.lld",
|
"linker-flavor": "ld.lld",
|
||||||
"linker": "rust-lld",
|
"linker": "rust-lld",
|
||||||
"panic-strategy": "abort",
|
"panic-strategy": "abort",
|
||||||
"disable-redzone": true,
|
"disable-redzone": true,
|
||||||
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
|
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user