Skip to content

Commit

Permalink
tmp commit
Browse files Browse the repository at this point in the history
  • Loading branch information
garasubo committed Jul 26, 2023
1 parent 2645f0d commit ebca635
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 236 deletions.
64 changes: 64 additions & 0 deletions docs/raspberry_pi4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Raspberry Pi4 Support
MilvusVisor has support for Raspberry Pi 4 environments.
We tested "Raspberry Pi 4 Computer Model B"

## Restricts
We currently support Only single core boot. Please add "nosmp" boot option, Otherwise Linux can boot, but MilvusVisor will not work fine.

## How to build
To enable Raspberry Pi 4 support, you need to add `edit_dtb_memory` feature flag on building binaries of hypervisor and bootloader.

```shell
make custom_all FEATURES=edit_dtb_memory
```

## How to boot
### Build U-boot
(This step assumed that your environment is Ubuntu. Otherwise, please replace the package names to suitable.)

1. Install `gcc-aarch64-linux-gnu` and `libssl-dev`
2. Clone u-boot and move into the directory
3. `export CROSS_COMPILE=aarch64-linux-gnu-`
4. Set configuration for Raspberry Pi 4: `make rpi_4_defconfig`
5. Build: `make`
6. Copy u-boot.bin

You can build in the docker with the below shell script(When run docker, don't forget bind directory to get the output binary :) )

```shell
#!/bin/sh
apt-get update
apt-get install -y build-essential bison flex gcc-aarch64-linux-gnu libssl-dev git make
git clone --depth=1 https://source.denx.de/u-boot/u-boot.git
cd u-boot
export CROSS_COMPILE=aarch64-linux-gnu-
make rpi_4_defconfig
make -j`nproc`
cp u-boot.bin /path/to/bound/
```

### Download "Raspberry Pi OS (64-bit)"
Go to https://www.raspberrypi.com/software/operating-systems/ , find "Raspberry Pi OS (64-bit)" section, and download "Raspberry Pi OS with desktop" or "Raspberry Pi OS Lite". (We tested with "Raspberry Pi OS Lite")


### Write image and binaries

1. Write the OS image to SD: (For example: `unxz 20XX-XX-XX-raspios-version-arm64-lite.img.xz && sudo dd if=20XX-XX-XX-raspios-version-arm64-lite.img of=/dev/mmcblk0 bs=10M status=progress`)
2. Mount SD Card: `sudo mount /dev/mmcblk0p1 /mnt`
3. Copy u-boot.bin: `sudo cp u-boot.bin /mnt/`
4. Copy MilvusVisor: `sudo cp -r /path/to/MlivusVisor/bin/EFI /mnt`
5. Modify config.txt: `sudo sed -i '/arm_64bit=1/akernel=u-boot.bin' /mnt/config.txt`
6. Modify config.txt: `sudo sed -i -e 's/console=serial0,115200 console=tty1//g' /mnt/cmdline.txt`
7. Enable UART(Optional): `sudo sed -i '/arm_64bit=1/adtoverlay=miniuart-bt\ncore_freq=250' /mnt/config.txt && sudo sed -i -e 's/quiet/console=ttyAMA0/g' /mnt/cmdline.txt`
8. Unmount: `sudo umount /mnt`

### How to Run
1. insert SD Card into Raspberry Pi 4
2. Connect UART(Optional)
3. Connect USB Power
4. Check DTB_ADDRESS which will printed by bootloader like `DTB_ADDRESS: 0x39EF7000`
5. Wait unti u-boot shows shell like `U-Boot>`
6. Load kernel8.img: `fatload mmc 0:1 ${kernel_addr_r} kernel8.img`
7. Set kernel_comp_size: `setenv kernel_comp_size ${filesize}`
8. Set kernel_comp_addr_r: `setenv kernel_comp_addr_r 0x3800000`
9. Boot Linux(`0x39EF7000` is DTB_ADDRESS, please change the value if different from checked value): `booti ${kernel_addr_r} - 0x39EF7000`
1 change: 0 additions & 1 deletion src/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ pub const HYPERVISOR_VIRTUAL_BASE_ADDRESS: usize = 0x7FC0000000;
pub const HYPERVISOR_SERIAL_BASE_ADDRESS: usize = 0x7FD0000000;
/// The memory size to allocate
pub const ALLOC_SIZE: usize = 256 * 1024 * 1024; /* 256 MB */
pub const ALLOC_SIZE_SUB: usize = 32 * 1024 * 1024; /* 32 MB */
pub const MAX_PHYSICAL_ADDRESS: usize = (1 << (52 + 1)) - 1; /* Armv8.2-A */
//pub const MAX_PHYSICAL_ADDRESS: usize = (1 << (48 + 1)) - 1;/* Armv8.0 */
pub const PAGE_SHIFT: usize = 12;
Expand Down
1 change: 0 additions & 1 deletion src/hypervisor_bootloader/.cargo/config
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[build]
target = "aarch64-unknown-uefi"
rustflags = ["-C", "target-feature=+v8.1a"]

[unstable]
build-std-features = ["compiler-builtins-mem"]
Expand Down
4 changes: 2 additions & 2 deletions src/hypervisor_bootloader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ mrs_msr_emulation = []
a64fx = ["mrs_msr_emulation"]
advanced_memory_manager = [] # Bootloader uses stack style allocator
tftp = []
u_boot = []
raspberrypi = ["u_boot"]
edit_dtb_memory = []
u_boot = ["edit_dtb_memory"]

[dependencies]
common = { path = "../common" }
Expand Down
183 changes: 57 additions & 126 deletions src/hypervisor_bootloader/src/dtb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ const FDT_NOP: u32 = 0x00000004u32.to_be();
const FDT_END: u32 = 0x00000009u32.to_be();
const TOKEN_SIZE: usize = 4;

//const NODE_NAME_SERIAL: &[u8] = "serial".as_bytes();

const PROP_STATUS: &[u8] = "status".as_bytes();
const PROP_STATUS_OKAY: &[u8] = "okay".as_bytes();
const PROP_COMPATIBLE: &[u8] = "compatible".as_bytes();
Expand Down Expand Up @@ -165,7 +163,7 @@ impl DtbNode {
&mut self,
target_prop_name: &[u8],
dtb: &DtbAnalyser,
) -> Result<Option<usize>, ()> {
) -> Result<Option<(usize, u32)>, ()> {
let mut pointer = self.base_pointer;
Self::skip_nop(&mut pointer);
if unsafe { *(pointer as *const u32) } != FDT_BEGIN_NODE {
Expand Down Expand Up @@ -198,7 +196,7 @@ impl DtbNode {
} else if Self::match_string(prop_name, PROP_SIZE_CELLS) {
self.size_cells = u32::from_be(unsafe { *(pointer as *const u32) });
} else if Self::match_string(prop_name, target_prop_name) {
return Ok(Some(pointer));
return Ok(Some((pointer, property_len)));
}

pointer += property_len as usize;
Expand Down Expand Up @@ -456,25 +454,73 @@ impl DtbNode {

pub fn is_status_okay(&self, dtb: &DtbAnalyser) -> Result<Option<bool>, ()> {
let mut s = self.clone();
if let Some(p) = s.search_pointer_to_property(PROP_STATUS, dtb)? {
if let Some((p, _)) = s.search_pointer_to_property(PROP_STATUS, dtb)? {
Ok(Some(Self::match_string(p, PROP_STATUS_OKAY)))
} else {
Ok(None)
}
}

pub fn get_offset(&self) -> usize {
self.address_offset
}

#[allow(dead_code)]
pub fn get_reg(&self, dtb: &DtbAnalyser) -> Result<Option<u64>, ()> {
pub fn get_reg(&self, dtb: &DtbAnalyser, index: usize) -> Result<(usize, usize), ()> {
let mut s = self.clone();
if let Some(mut _p) = s.search_pointer_to_property(PROP_REG, dtb)? {
unimplemented!()
if let Some((mut p, property_len)) = s.search_pointer_to_property(PROP_REG, dtb)? {
let offset = index * ((self.address_cells + self.size_cells) as usize) * TOKEN_SIZE;
if offset >= property_len as usize {
return Err(());
}
p += offset;
let mut address = 0usize;
let mut size = 0usize;
for _ in 0..self.address_cells {
address <<= u32::BITS;
address |= u32::from_be(unsafe { *(p as *const u32) }) as usize;
p += TOKEN_SIZE;
}
for _ in 0..self.size_cells {
size <<= u32::BITS;
size |= u32::from_be(unsafe { *(p as *const u32) }) as usize;
p += TOKEN_SIZE;
}
return Ok((address, size));
} else {
Ok(None)
Err(())
}
}

pub fn get_offset(&self) -> usize {
self.address_offset
#[allow(dead_code)]
pub fn edit_reg(
&self,
dtb: &DtbAnalyser,
index: usize,
address: usize,
size: usize,
) -> Result<(), ()> {
let mut s = self.clone();
if let Some((mut p, property_len)) = s.search_pointer_to_property(PROP_REG, dtb)? {
let offset = index * ((self.address_cells + self.size_cells) as usize) * TOKEN_SIZE;
if offset >= property_len as usize {
return Err(());
}
p += offset;
for i in (0..(self.address_cells as usize)).rev() {
let a = ((address >> (u32::BITS as usize * i)) & (u32::MAX as usize)) as u32;
unsafe { core::ptr::write_volatile(p as *mut u32, a.to_be()) };
p += TOKEN_SIZE;
}
for i in (0..(self.size_cells as usize)).rev() {
let a = ((size >> (u32::BITS as usize * i)) & (u32::MAX as usize)) as u32;
unsafe { core::ptr::write_volatile(p as *mut u32, a.to_be()) };
p += TOKEN_SIZE;
}
Ok(())
} else {
Err(())
}
}
}

Expand Down Expand Up @@ -567,118 +613,3 @@ impl DtbAnalyser {
self.struct_block_size + self.struct_block_address
}
}

#[cfg(feature = "raspberrypi")]
pub fn add_new_memory_reservation_entry_to_dtb(
original_base_address: usize,
new_base_address: usize,
new_size: usize,
reserved_address: usize,
reserved_size: usize,
) -> Result<(), ()> {
let mut total_new_size = 0;
let original_dtb_header = unsafe { &*(original_base_address as *const DtbHeader) };

let new_dtb_header = unsafe { &mut *(new_base_address as *mut DtbHeader) };
total_new_size += core::mem::size_of::<DtbHeader>();
if new_size < total_new_size {
return Err(());
}

new_dtb_header.magic = original_dtb_header.magic;
new_dtb_header.version = original_dtb_header.version;
new_dtb_header.last_comp_version = original_dtb_header.last_comp_version;
new_dtb_header.boot_cpuid_phys = original_dtb_header.boot_cpuid_phys;
new_dtb_header.size_dt_struct = original_dtb_header.size_dt_struct;
new_dtb_header.size_dt_strings = original_dtb_header.size_dt_strings;

// copy memory reservation block and add new reservation entry
let original_reservation_block_address =
original_base_address + u32::from_be(original_dtb_header.off_mem_rsv_map) as usize;
let new_reservation_block_address = new_base_address + total_new_size;
let mut pointer = original_reservation_block_address;
loop {
let address = unsafe { *(pointer as *const u64) };
pointer += core::mem::size_of::<u64>();
let size = unsafe { *(pointer as *const u64) };
pointer += core::mem::size_of::<u64>();
if address == 0 && size == 0 {
break;
}
}
// original reservation block size without terminal entry
let reservation_block_section_size =
pointer - original_reservation_block_address - core::mem::size_of::<u64>() * 2;
// new total size will be the size of original reservation block + new entry + terminal entry
total_new_size += reservation_block_section_size + core::mem::size_of::<u64>() * 4;
if new_size < total_new_size {
return Err(());
}
unsafe {
// copy original mrb to new mrb
core::ptr::copy_nonoverlapping(
original_reservation_block_address as *const u8,
new_reservation_block_address as *mut u8,
reservation_block_section_size,
);
}
unsafe {
// write new entries
let new_reservation_entry_address_filed_address =
new_reservation_block_address + reservation_block_section_size;
let new_reservation_entry_size_field_address = new_reservation_block_address
+ reservation_block_section_size
+ core::mem::size_of::<u64>();
*(new_reservation_entry_address_filed_address as *mut usize) = reserved_address.to_be();
*(new_reservation_entry_size_field_address as *mut usize) = reserved_size.to_be();
let new_termianal_entry_address = new_reservation_block_address
+ reservation_block_section_size
+ core::mem::size_of::<u64>() * 2;
*(new_termianal_entry_address as *mut usize) = 0;
*((new_termianal_entry_address + core::mem::size_of::<u64>()) as *mut usize) = 0;
}

// copy struct section
let new_struct_base_address = new_base_address + total_new_size;
let original_struct_base_address =
original_base_address + u32::from_be(original_dtb_header.off_dt_struct) as usize;
let struct_section_size = u32::from_be(original_dtb_header.size_dt_struct) as usize;
total_new_size += struct_section_size;
if total_new_size > new_size {
return Err(());
}
unsafe {
core::ptr::copy_nonoverlapping(
original_struct_base_address as *const u8,
new_struct_base_address as *mut u8,
struct_section_size,
);
}

// copy string section
let new_string_section_address = new_base_address + total_new_size;
let original_string_section_address =
original_base_address + u32::from_be(original_dtb_header.off_dt_strings) as usize;
let string_section_size = u32::from_be(original_dtb_header.size_dt_strings) as usize;
total_new_size += string_section_size;
if total_new_size > new_size {
return Err(());
}
unsafe {
core::ptr::copy_nonoverlapping(
original_string_section_address as *const u8,
new_string_section_address as *mut u8,
u32::from_be(original_dtb_header.size_dt_strings) as usize,
);
}

// edit header
new_dtb_header.off_mem_rsv_map =
((new_reservation_block_address - new_base_address) as u32).to_be();
new_dtb_header.off_dt_struct = ((new_struct_base_address - new_base_address) as u32).to_be();
new_dtb_header.off_dt_strings =
((new_string_section_address - new_base_address) as u32).to_be();
new_dtb_header.total_size = (total_new_size as u32).to_be();

Ok(())
}
Loading

0 comments on commit ebca635

Please sign in to comment.