Skip to content

Commit 91ffb47

Browse files
committed
This project is now a bootloader. It will send three breaks to request a kernel to relocate to. Use 'pusher' to send your kernel
1 parent 02cc435 commit 91ffb47

File tree

8 files changed

+98
-52
lines changed

8 files changed

+98
-52
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ edition = "2021"
77
lto = true
88

99
[features]
10-
default = []
10+
default = ["bsp_rpi3"]
1111
bsp_rpi3 = []
1212
bsp_rpi4 = []
1313

Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ ifeq ($(BSP),rpi3)
3131
NM_BINARY = aarch64-unknown-linux-gnu-nm
3232
READELF_BINARY = aarch64-unknown-linux-gnu-readelf
3333
LINKER_FILE = src/bsp/raspberrypi/link.ld
34-
RUSTC_MISC_ARGS = -C target-cpu=cortex-a53
34+
RUSTC_MISC_ARGS = -C target-cpu=cortex-a53
3535
else ifeq ($(BSP),rpi4)
3636
TARGET = aarch64-unknown-none-softfloat
3737
KERNEL_BIN = kernel8.img
@@ -56,7 +56,7 @@ KERNEL_ELF = target/$(TARGET)/release/kernel
5656
## Command building blocks
5757
##--------------------------------------------------------------------------------------------------
5858
RUSTFLAGS = -C link-arg=-T$(LINKER_FILE) $(RUSTC_MISC_ARGS)
59-
RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) -D missing_docs -D warnings
59+
RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) -D missing_docs -D warnings
6060

6161
# for conditional compiling (rpi3, rpi4 etc...)
6262
FEATURES = --features bsp_$(BSP)
@@ -158,4 +158,4 @@ nm: $(KERNEL_ELF)
158158
## Helper target for rust-analyzer
159159
##------------------------------------------------------------------------------
160160
check:
161-
@RUSTFLAGS="$(RUSTFLAGS)" $(CHECK_CMD) --message-format=json
161+
@RUSTFLAGS="$(RUSTFLAGS)" $(CHECK_CMD) --message-format=json

src/_arch/aarch64/cpu/boot.s

+32-12
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@ https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html
2828
add \register, \register, #:lo12:\symbol
2929
.endm
3030

31+
// Load the address of a symbol into a register, absolute.
32+
//
33+
// # Resources
34+
//
35+
// - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html
36+
.macro ADR_ABS register, symbol
37+
movz \register, #:abs_g2:\symbol
38+
movk \register, #:abs_g1_nc:\symbol
39+
movk \register, #:abs_g0_nc:\symbol
40+
.endm
41+
3142
.equ _core_id_mask, 0b11
3243

3344
.section .text._start
@@ -45,28 +56,37 @@ _start:
4556
b.ne _park_core
4657

4758
// the core executing these lines is the boot core
48-
ADR_REL x0, __bss_start
49-
ADR_REL x1, __bss_end_exclusive
59+
ADR_ABS x0, __bss_start
60+
ADR_ABS x1, __bss_end_exclusive
5061

5162
_initialize_bss:
5263
cmp x0, x1
53-
b.eq _prepare_rust // break the loop if we reached ens of bss
64+
b.eq _relocate_bootloader // break the loop if we reached end of bss
5465
stp xzr, xzr, [x0], #16 // store two zero values (xzr=0) in the bss section
5566
b _initialize_bss
5667

57-
_prepare_rust:
58-
// setting up stack:
59-
// sp start from pointing at the end of the bss section,
60-
// and it grows downwards (0x7999 - 0x0000)
61-
ADR_REL x0, __boot_core_stack_end_exclusive
62-
mov sp, x0
63-
// let's begin!
64-
b _start_rust
68+
_relocate_bootloader:
69+
ADR_REL x0, __binary_start // Where the binary was loaded (ex. 0x8000)
70+
ADR_ABS x1, __binary_start // Where the binary was linked (ex. 0x2000000)
71+
ADR_ABS x2, __binary_end_exclusive // End of the binary.
72+
73+
_copy_loop:
74+
ldr x3, [x0], #8 // load to x3 whatever is in x0, advance x0 by 8
75+
str x3, [x1], #8 // store whatever is in x3 in the address of x3, advance by 8 x1
76+
cmp x1, x2
77+
b.lo _copy_loop
78+
79+
// setting up stack:
80+
ADR_ABS x0, __boot_core_stack_end_exclusive
81+
mov sp, x0
82+
// let's begin!
83+
ADR_ABS x0, _start_rust
84+
br x0
6585

6686
_park_core:
6787
wfe // wait for event
6888
b _park_core // jump to loop if event occured.
6989

7090
.size _start, . - _start // tells the linker the size of _start, doesn't look important
7191
.type _start, function // start is a function
72-
.global _start // _start is an external symbol ready to link
92+
.global _start // _start is an external symbol ready to link

src/bsp/device_driver/bcm/bcm2xxx_gpio.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
use crate::{
9-
bsp::device_driver::common::MMIODerefWrapper, driver, synchronization::{interface::Mutex},
9+
bsp::device_driver::common::MMIODerefWrapper, driver, synchronization::interface::Mutex,
1010
synchronization::NullLock,
1111
};
1212

src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use core::fmt;
99
use core::fmt::Arguments;
1010

1111
use crate::{
12-
bsp::device_driver::common::MMIODerefWrapper, driver, synchronization::{interface::Mutex},
12+
bsp::device_driver::common::MMIODerefWrapper, driver, synchronization::interface::Mutex,
1313
synchronization::NullLock, cpu, console,
1414
};
1515

@@ -228,8 +228,8 @@ impl PL011UartInner {
228228
self.registers.ICR.write(ICR::ALL::CLEAR);
229229

230230
// set IBRD + FBRD and enable FIFO and 8N1
231-
self.registers.IBRD.write(IBRD::IBRD_DIVINT.val(3));
232-
self.registers.FBRD.write(FBRD::FBRD_DIVFRAC.val(16));
231+
self.registers.IBRD.write(IBRD::IBRD_DIVINT.val(26));
232+
self.registers.FBRD.write(FBRD::FBRD_DIVFRAC.val(3));
233233
self.registers
234234
.LCR_H.write(LCR_H::WLEN::EightBits + LCR_H::FEN::Enabled);
235235

@@ -275,14 +275,9 @@ impl PL011UartInner {
275275
}
276276

277277
// read char
278-
let mut ret = self.registers.DR.get() as u8 as char;
279-
280-
if ret == '\r' {
281-
ret = '\n';
282-
}
278+
let ret = self.registers.DR.get() as u8 as char;
283279

284280
self.chars_read += 1;
285-
286281
Some(ret)
287282
}
288283
}

src/bsp/raspberrypi/link.ld

+8-9
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ PHDRS
2828

2929
SECTIONS
3030
{
31-
. = 0;
31+
. = 0x2000000; /* link address. The bootloader with relocate here before loading the kernel */
3232

3333
/*
3434
This is the "start" of the stack section for the boot core.
@@ -40,10 +40,8 @@ SECTIONS
4040
__boot_core_stack_end_exclusive = .;
4141
} :segment_boot_core_stack
4242

43-
/*
44-
Code section. the first instruction is in kernel_addr_in_memory
45-
create a section called text where code will live
46-
*/
43+
/* Code section. */
44+
__binary_start = .;
4745
.text :
4846
{
4947
KEEP(*(.text._start)) /* found in boot.s */
@@ -52,15 +50,16 @@ SECTIONS
5250
*(.text*) /* the rest */
5351
} :segment_code
5452

55-
.rodata : ALIGN(8)
56-
{
57-
*(.rodata*)
58-
} :segment_code
53+
.rodata : ALIGN(8) { *(.rodata*) } :segment_code
5954

6055
.got : ALIGN(8) { *(.got) } :segment_code
6156

6257
.data : { *(.data*) } :segment_data
6358

59+
. = ALIGN(8);
60+
61+
__binary_end_exclusive = .;
62+
6463
/* bsses */
6564
.bss (NOLOAD) : ALIGN(16)
6665
{

src/bsp/raspberrypi/memory.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
// that need to be mapped physically.
1212

1313
pub mod map {
14+
pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
15+
1416
pub const GPIO_OFFSET: usize = 0x0020_0000;
1517
pub const UART_OFFSET: usize = 0x0020_1000;
1618

@@ -33,4 +35,9 @@ pub mod map {
3335
pub const GPIO_START: usize = START + GPIO_OFFSET;
3436
pub const PL011_UART_START: usize = START + UART_OFFSET;
3537
}
36-
}
38+
}
39+
40+
#[inline(always)]
41+
pub fn board_default_load_address() -> *const u64 {
42+
map::BOARD_DEFAULT_LOAD_ADDRESS as _
43+
}

src/main.rs

+41-16
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
//! Enter point of, well, everything
44
//! Well, not really, more general metadata, module definitions etc...
5-
#![feature(const_fn_fn_ptr_basics)]
65
#![feature(format_args_nl)]
76
#![feature(panic_info_message)]
87
#![feature(trait_alias)]
@@ -36,26 +35,52 @@ unsafe fn kernel_init() -> ! {
3635
kernel_main();
3736
}
3837

38+
const LOADER_LOGO: &str = r#"
39+
.____ .___
40+
| | _________ __| _/___________
41+
| | / _ \__ \ / __ |/ __ \_ __ \
42+
| |__( <_> ) __ \_/ /_/ \ ___/| | \/
43+
|_______ \____(____ /\____ |\___ >__|
44+
\/ \/ \/ \/
45+
"#;
46+
3947
fn kernel_main() -> ! {
4048
use bsp::console::console;
4149
use console::interface::All;
42-
use driver::interface::DeviceManager;
4350

44-
println!("RpiOS is booting...");
45-
println!("Communicating through PL011 UART");
51+
println!("{}", LOADER_LOGO);
52+
println!("Running on: {}", bsp::board_name());
53+
println!();
54+
println!("Requesting binary!");
55+
console().flush();
56+
57+
console().clear_rx();
4658

47-
println!("[1] Booting on: {}", bsp::board_name());
48-
println!("[2] Drivers loaded:");
49-
for (i, driver) in bsp::driver::driver_manager().all_device_drivers().iter().enumerate(){
50-
println!("{}. {}", i+1, driver.compatible());
59+
// send three times '3' through UART to notify the pusher to send the kernel / binary
60+
for _ in 0..3 {
61+
console().write_char(3 as char);
5162
}
5263

53-
println!("[3] Chars written: {}", bsp::console::console().chars_written());
64+
// Read the binary's size.
65+
let mut size: u32 = u32::from(console().read_char() as u8);
66+
size |= u32::from(console().read_char() as u8) << 8;
67+
size |= u32::from(console().read_char() as u8) << 16;
68+
size |= u32::from(console().read_char() as u8) << 24;
5469

55-
println!("[4] Entering echo mode");
56-
console().clear_rx();
57-
loop {
58-
let c = bsp::console::console().read_char();
59-
bsp::console::console().write_char(c);
60-
}
61-
}
70+
console().write_char('O');
71+
console().write_char('K');
72+
73+
let kernel_addr = bsp::memory::board_default_load_address() as *mut u8;
74+
75+
unsafe {
76+
for i in 0..size {
77+
core::ptr::write_volatile(kernel_addr.offset(i as isize), console().read_char() as u8);
78+
}
79+
}
80+
81+
println!("Received kernel, executing now!");
82+
console().flush();
83+
84+
let kernel: fn() -> ! = unsafe { core::mem::transmute(kernel_addr) };
85+
kernel();
86+
}

0 commit comments

Comments
 (0)