bootloader: add basic network support.

This commit is contained in:
whitequark 2017-12-28 14:51:20 +00:00
parent d2687ce3c4
commit 3505878176
4 changed files with 84 additions and 24 deletions

View File

@ -29,6 +29,7 @@ dependencies = [
"build_misoc 0.0.0", "build_misoc 0.0.0",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=507d2fe)",
] ]
[[package]] [[package]]
@ -49,8 +50,9 @@ dependencies = [
"board 0.0.0", "board 0.0.0",
"build_misoc 0.0.0", "build_misoc 0.0.0",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.1.0 (git+https://github.com/m-labs/compiler-builtins?rev=97916b1)",
"crc 1.6.0 (git+git://github.com/whitequark/crc-rs?rev=51cd356)", "crc 1.6.0 (git+git://github.com/whitequark/crc-rs?rev=51cd356)",
"rlibc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=507d2fe)",
] ]
[[package]] [[package]]
@ -199,11 +201,6 @@ dependencies = [
"std_artiq 0.0.0", "std_artiq 0.0.0",
] ]
[[package]]
name = "rlibc"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "runtime" name = "runtime"
version = "0.0.0" version = "0.0.0"
@ -307,7 +304,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
"checksum log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec57723b84bbe7bdf76aa93169c9b59e67473317c6de3a83cb2a0f8ccb2aa493" "checksum log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec57723b84bbe7bdf76aa93169c9b59e67473317c6de3a83cb2a0f8ccb2aa493"
"checksum managed 0.4.0 (git+https://github.com/m-labs/rust-managed.git?rev=629a6786a1cf1692015f464ed16c04eafa5cb8d1)" = "<none>" "checksum managed 0.4.0 (git+https://github.com/m-labs/rust-managed.git?rev=629a6786a1cf1692015f464ed16c04eafa5cb8d1)" = "<none>"
"checksum rlibc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe"
"checksum rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a596b5718bf5e059d59a30af12f7f462a152de147aa462b70892849ee18704" "checksum rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a596b5718bf5e059d59a30af12f7f462a152de147aa462b70892849ee18704"
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
"checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=507d2fe)" = "<none>" "checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=507d2fe)" = "<none>"

View File

@ -13,7 +13,17 @@ path = "main.rs"
build_misoc = { path = "../libbuild_misoc" } build_misoc = { path = "../libbuild_misoc" }
[dependencies] [dependencies]
rlibc = "1.0"
byteorder = { version = "1.0", default-features = false } byteorder = { version = "1.0", default-features = false }
crc = { git = "git://github.com/whitequark/crc-rs", rev = "51cd356", default-features = false } crc = { git = "git://github.com/whitequark/crc-rs", rev = "51cd356", default-features = false }
board = { path = "../libboard", features = ["uart_console"] } board = { path = "../libboard", features = ["uart_console", "smoltcp"] }
[dependencies.compiler_builtins]
git = "https://github.com/m-labs/compiler-builtins"
rev = "97916b1"
features = ["mem"]
[dependencies.smoltcp]
git = "https://github.com/m-labs/smoltcp"
rev = "507d2fe"
default-features = false
features = ["proto-ipv4", "socket-tcp"]

View File

@ -28,7 +28,7 @@ SECTIONS
. += 4; . += 4;
} }
.bss ALIGN(4) : .bss :
{ {
_fbss = .; _fbss = .;
*(.bss .bss.*) *(.bss .bss.*)

View File

@ -1,16 +1,18 @@
#![no_std] #![no_std]
#![feature(lang_items)] #![feature(lang_items, compiler_builtins_lib)]
extern crate rlibc; extern crate compiler_builtins;
extern crate crc; extern crate crc;
extern crate byteorder; extern crate byteorder;
extern crate smoltcp;
#[macro_use] #[macro_use]
extern crate board; extern crate board;
use core::{ptr, slice}; use core::{ptr, slice};
use crc::crc32; use crc::crc32;
use byteorder::{ByteOrder, BigEndian}; use byteorder::{ByteOrder, BigEndian};
use board::{boot, cache}; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
use board::{boot, cache, clock, config, ethmac};
use board::uart_console::Console; use board::uart_console::Console;
fn check_integrity() -> bool { fn check_integrity() -> bool {
@ -28,7 +30,7 @@ fn check_integrity() -> bool {
} }
} }
unsafe fn memory_test(total: &mut usize, wrong: &mut usize) -> bool { fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
const MEMORY: *mut u32 = board::mem::MAIN_RAM_BASE as *mut u32; const MEMORY: *mut u32 = board::mem::MAIN_RAM_BASE as *mut u32;
*total = 0; *total = 0;
@ -43,7 +45,7 @@ unsafe fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
) => ({ ) => ({
$prepare; $prepare;
for $i in $range { for $i in $range {
ptr::write_volatile(MEMORY.offset($index as isize), $data); unsafe { ptr::write_volatile(MEMORY.offset($index as isize), $data) };
*total += 1; *total += 1;
} }
@ -52,7 +54,7 @@ unsafe fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
$prepare; $prepare;
for $i in $range { for $i in $range {
if ptr::read_volatile(MEMORY.offset($index as isize)) != $data { if unsafe { ptr::read_volatile(MEMORY.offset($index as isize)) } != $data {
*wrong += 1; *wrong += 1;
} }
} }
@ -95,7 +97,7 @@ fn startup() -> bool {
} }
let (mut total, mut wrong) = (0, 0); let (mut total, mut wrong) = (0, 0);
if unsafe { memory_test(&mut total, &mut wrong) } { if memory_test(&mut total, &mut wrong) {
println!("Memory test passed"); println!("Memory test passed");
} else { } else {
println!("Memory test failed ({}/{} words incorrect)", wrong, total); println!("Memory test failed ({}/{} words incorrect)", wrong, total);
@ -105,36 +107,81 @@ fn startup() -> bool {
true true
} }
unsafe fn flash_boot() { fn flash_boot() {
const FIRMWARE: *mut u8 = board::mem::FLASH_BOOT_ADDRESS as *mut u8; const FIRMWARE: *mut u8 = board::mem::FLASH_BOOT_ADDRESS as *mut u8;
const MAIN_RAM: *mut u8 = board::mem::MAIN_RAM_BASE as *mut u8; const MAIN_RAM: *mut u8 = board::mem::MAIN_RAM_BASE as *mut u8;
println!("Booting from flash..."); println!("Booting from flash...");
let header = slice::from_raw_parts(FIRMWARE, 8); let header = unsafe { slice::from_raw_parts(FIRMWARE, 8) };
let length = BigEndian::read_u32(&header[0..]) as usize; let length = BigEndian::read_u32(&header[0..]) as usize;
let expected_crc = BigEndian::read_u32(&header[4..]); let expected_crc = BigEndian::read_u32(&header[4..]);
if length == 0xffffffff { if length == 0xffffffff {
println!("No firmware present"); println!("No firmware present");
return return
} else if length > 4 * 1024 * 1024 {
println!("Firmware too large (is it corrupted?)");
return
} }
let firmware_in_flash = slice::from_raw_parts(FIRMWARE.offset(8), length); let firmware_in_flash = unsafe { slice::from_raw_parts(FIRMWARE.offset(8), length) };
let actual_crc = crc32::checksum_ieee(firmware_in_flash); let actual_crc = crc32::checksum_ieee(firmware_in_flash);
if actual_crc == expected_crc { if actual_crc == expected_crc {
let firmware_in_sdram = slice::from_raw_parts_mut(MAIN_RAM, length); let firmware_in_sdram = unsafe { slice::from_raw_parts_mut(MAIN_RAM, length) };
firmware_in_sdram.copy_from_slice(firmware_in_flash); firmware_in_sdram.copy_from_slice(firmware_in_flash);
println!("Starting firmware."); println!("Starting firmware.");
boot::jump(MAIN_RAM as usize); unsafe { boot::jump(MAIN_RAM as usize) }
} else { } else {
println!("Firmware CRC failed (actual {:08x}, expected {:08x}", println!("Firmware CRC failed (actual {:08x}, expected {:08x})",
actual_crc, expected_crc); actual_crc, expected_crc);
} }
} }
fn network_boot() {
println!("Initializing network...");
let eth_addr = match config::read_str("mac", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => addr,
_ => EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01])
};
let ip_addr = match config::read_str("ip", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => addr,
_ => IpAddress::v4(192, 168, 1, 50)
};
println!("Using MAC address {} and IP address {}", eth_addr, ip_addr);
let net_device = unsafe { ethmac::EthernetDevice::new() };
let mut neighbor_cache_storage = [None; 2];
let neighbor_cache =
smoltcp::iface::NeighborCache::new(&mut neighbor_cache_storage[..]);
let mut ip_addrs = [IpCidr::new(ip_addr, 0)];
let mut interface =
smoltcp::iface::EthernetInterfaceBuilder::new(net_device)
.neighbor_cache(neighbor_cache)
.ethernet_addr(eth_addr)
.ip_addrs(&mut ip_addrs[..])
.finalize();
let mut socket_set_storage = [];
let mut sockets =
smoltcp::socket::SocketSet::new(&mut socket_set_storage[..]);
println!("Waiting for connections...");
loop {
match interface.poll(&mut sockets, clock::get_ms()) {
Ok(_) => (),
Err(smoltcp::Error::Unrecognized) => (),
Err(err) => println!("Network error: {}", err)
}
}
}
#[no_mangle] #[no_mangle]
pub extern fn main() -> i32 { pub extern fn main() -> i32 {
println!(""); println!("");
@ -150,7 +197,8 @@ pub extern fn main() -> i32 {
if startup() { if startup() {
println!(""); println!("");
unsafe { flash_boot() }; flash_boot();
network_boot();
} else { } else {
println!("Halting."); println!("Halting.");
} }
@ -163,6 +211,12 @@ pub extern fn exception(vect: u32, _regs: *const u32, pc: u32, ea: u32) {
panic!("exception {} at PC {:#08x}, EA {:#08x}", vect, pc, ea) panic!("exception {} at PC {:#08x}, EA {:#08x}", vect, pc, ea)
} }
#[no_mangle]
pub extern fn abort() {
println!("aborted");
loop {}
}
#[no_mangle] #[no_mangle]
#[lang = "panic_fmt"] #[lang = "panic_fmt"]
pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) -> ! { pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) -> ! {