1
0
Fork 0

fixed bugs + missing methods

This commit is contained in:
Simon Renblad 2024-10-07 14:59:00 +08:00
parent c528721b42
commit 10b03da5ce
5 changed files with 115 additions and 66 deletions

View File

@ -1,9 +1,12 @@
use alloc::vec::Vec; use alloc::vec::Vec;
use crate::sd_reader::Error use fatfs::{self, IoBase, Read, Seek, SeekFrom};
use fatfs::io::{Read, Seek, SeekFrom};
use libboard_zynq::devc; use libboard_zynq::devc;
use crate::sd_reader;
use crate::File;
use log::debug; use log::debug;
type Error = fatfs::Error<sd_reader::Error>;
#[derive(Debug)] #[derive(Debug)]
pub enum BootgenLoadingError { pub enum BootgenLoadingError {
InvalidBootImageHeader, InvalidBootImageHeader,
@ -13,8 +16,8 @@ pub enum BootgenLoadingError {
DevcError(devc::DevcError), DevcError(devc::DevcError),
} }
impl From<sd_reader::Error> for BootgenLoadingError { impl From<Error> for BootgenLoadingError {
fn from(error: sd_reader::Error) -> Self { fn from(error: Error) -> Self {
BootgenLoadingError::IoError(error) BootgenLoadingError::IoError(error)
} }
} }
@ -59,7 +62,7 @@ struct PartitionHeader {
} }
/// Read a u32 word from the reader. /// Read a u32 word from the reader.
fn read_u32<Reader: Read>(reader: &mut Reader) -> Result<u32, BootgenLoadingError> { fn read_u32<'a>(reader: &mut File<'a>) -> Result<u32, BootgenLoadingError> {
let mut buffer: [u8; 4] = [0; 4]; let mut buffer: [u8; 4] = [0; 4];
reader.read_exact(&mut buffer)?; reader.read_exact(&mut buffer)?;
let mut result: u32 = 0; let mut result: u32 = 0;
@ -70,8 +73,8 @@ fn read_u32<Reader: Read>(reader: &mut Reader) -> Result<u32, BootgenLoadingErro
} }
/// Load PL partition header. /// Load PL partition header.
fn load_pl_header<File: Read + Seek>( fn load_pl_header<'a>(
file: &mut File, file: &mut File<'a>,
) -> Result<Option<PartitionHeader>, BootgenLoadingError> { ) -> Result<Option<PartitionHeader>, BootgenLoadingError> {
let mut buffer: [u8; 0x40] = [0; 0x40]; let mut buffer: [u8; 0x40] = [0; 0x40];
file.read_exact(&mut buffer)?; file.read_exact(&mut buffer)?;
@ -83,8 +86,8 @@ fn load_pl_header<File: Read + Seek>(
} }
} }
fn load_ps_header<File: Read + Seek>( fn load_ps_header<'a>(
file: &mut File, file: &mut File<'a>,
) -> Result<Option<PartitionHeader>, BootgenLoadingError> { ) -> Result<Option<PartitionHeader>, BootgenLoadingError> {
let mut buffer: [u8; 0x40] = [0; 0x40]; let mut buffer: [u8; 0x40] = [0; 0x40];
file.read_exact(&mut buffer)?; file.read_exact(&mut buffer)?;
@ -99,10 +102,10 @@ fn load_ps_header<File: Read + Seek>(
/// Locate the partition from the image, and return the size (in bytes) of the partition if successful. /// Locate the partition from the image, and return the size (in bytes) of the partition if successful.
/// This function would seek the file to the location of the partition. /// This function would seek the file to the location of the partition.
fn locate< fn locate<
File: Read + Seek, 'a,
F: Fn(&mut File) -> Result<Option<PartitionHeader>, BootgenLoadingError>, F: Fn(&mut File<'a>) -> Result<Option<PartitionHeader>, BootgenLoadingError>,
>( >(
file: &mut File, file: &mut File<'a>,
f: F, f: F,
) -> Result<usize, BootgenLoadingError> { ) -> Result<usize, BootgenLoadingError> {
file.seek(SeekFrom::Start(0))?; file.seek(SeekFrom::Start(0))?;
@ -150,7 +153,7 @@ fn locate<
/// Load bitstream from bootgen file. /// Load bitstream from bootgen file.
/// This function parses the file, locate the bitstream and load it through the PCAP driver. /// This function parses the file, locate the bitstream and load it through the PCAP driver.
/// It requires a large buffer, please enable the DDR RAM before using it. /// It requires a large buffer, please enable the DDR RAM before using it.
pub fn load_bitstream<File: Read + Seek>(file: &mut File) -> Result<(), BootgenLoadingError> { pub fn load_bitstream<'a>(file: &mut File<'a>) -> Result<(), BootgenLoadingError> {
let size = locate(file, load_pl_header)?; let size = locate(file, load_pl_header)?;
unsafe { unsafe {
// align to 64 bytes // align to 64 bytes
@ -171,7 +174,7 @@ pub fn load_bitstream<File: Read + Seek>(file: &mut File) -> Result<(), BootgenL
} }
} }
pub fn get_runtime<File: Read + Seek>(file: &mut File) -> Result<Vec<u8>, BootgenLoadingError> { pub fn get_runtime<'a>(file: &mut File<'a>) -> Result<Vec<u8>, BootgenLoadingError> {
let size = locate(file, load_ps_header)?; let size = locate(file, load_ps_header)?;
let mut buffer = Vec::with_capacity(size); let mut buffer = Vec::with_capacity(size);
unsafe { unsafe {

View File

@ -1,19 +1,24 @@
#![no_std] #![no_std]
extern crate alloc; extern crate alloc;
use alloc::{rc::Rc, string::FromUtf8Error, string::String, vec::Vec};
use sd_reader::SdReader;
use core::fmt; use core::fmt;
use alloc::{string::FromUtf8Error, string::String, vec::Vec, rc::Rc}; use fatfs::{self, IoBase, Read, Seek, SeekFrom, Write};
use fatfs::io::{Read, Write, Seek, SeekFrom}
use libboard_zynq::sdio; use libboard_zynq::sdio;
pub mod sd_reader;
pub mod net_settings;
pub mod bootgen; pub mod bootgen;
pub mod net_settings;
pub mod sd_reader;
type SdReadError = fatfs::Error<sd_reader::Error>;
pub type File<'a> = fatfs::File<'a, SdReader, fatfs::NullTimeProvider, fatfs::LossyOemCpConverter>;
#[derive(Debug)] #[derive(Debug)]
pub enum Error<'a> { pub enum Error<'a> {
SdError(sdio::sd_card::CardInitializationError), SdError(sdio::sd_card::CardInitializationError),
IoError(sd_reader::Error), IoError(SdReadError),
Utf8Error(FromUtf8Error), Utf8Error(FromUtf8Error),
KeyNotFoundError(&'a str), KeyNotFoundError(&'a str),
NoConfig, NoConfig,
@ -39,8 +44,8 @@ impl<'a> From<sdio::sd_card::CardInitializationError> for Error<'a> {
} }
} }
impl<'a> From<sd_reader::Error> for Error<'a> { impl<'a> From<SdReadError> for Error<'a> {
fn from(error: sd_reader::Error) -> Self { fn from(error: SdReadError) -> Self {
Error::IoError(error) Error::IoError(error)
} }
} }
@ -51,14 +56,31 @@ impl<'a> From<FromUtf8Error> for Error<'a> {
} }
} }
fn read_to_string<'a>(file: &mut File<'a>, read_str: &mut String) -> Result<'a, ()> {
let mut buffer = Vec::new();
let mut temp_buffer = [0; 500];
loop {
let read_bytes = file.read(&mut temp_buffer)?;
if read_bytes != buffer.len() {
buffer.extend_from_slice(&temp_buffer[..read_bytes]);
break;
}
else {
buffer.extend_from_slice(&temp_buffer);
}
}
read_str.extend(String::from_utf8(buffer));
Ok(())
}
fn parse_config<'a>( fn parse_config<'a>(
key: &'a str, key: &'a str,
buffer: &mut Vec<u8>, buffer: &mut Vec<u8>,
file: fatfs::File<sd_reader::SdReader>, mut file: File<'a>,
) -> Result<'a, ()> { ) -> Result<'a, ()> {
let prefix = [key, "="].concat().to_ascii_lowercase(); let prefix = [key, "="].concat().to_ascii_lowercase();
let mut read_buffer = String::new(); let mut read_buffer = String::new();
file.read_to_string(&mut read_buffer); read_to_string(&mut file, &mut read_buffer)?;
for line in read_buffer.lines() { for line in read_buffer.lines() {
let line = line.to_ascii_lowercase(); let line = line.to_ascii_lowercase();
if line.starts_with(&prefix) { if line.starts_with(&prefix) {
@ -85,7 +107,9 @@ impl Config {
let reader = sd_reader::SdReader::new(sd); let reader = sd_reader::SdReader::new(sd);
let fs = reader.mount_fatfs(sd_reader::PartitionEntry::Entry1)?; let fs = reader.mount_fatfs(sd_reader::PartitionEntry::Entry1)?;
Ok(Config { fs: Some(Rc::new(fs)) }) Ok(Config {
fs: Some(Rc::new(fs)),
})
} }
pub fn from_fs(fs: Option<Rc<fatfs::FileSystem<sd_reader::SdReader>>>) -> Self { pub fn from_fs(fs: Option<Rc<fatfs::FileSystem<sd_reader::SdReader>>>) -> Self {
@ -96,12 +120,12 @@ impl Config {
Config { fs: None } Config { fs: None }
} }
pub fn read<'b>(&self, key: &'b str) -> Result<'b, Vec<u8>> { pub fn read<'b>(&'b self, key: &'b str) -> Result<'b, Vec<u8>> {
if let Some(fs) = &self.fs { if let Some(fs) = &self.fs {
let root_dir = fs.root_dir(); let root_dir = fs.root_dir();
let mut buffer: Vec<u8> = Vec::new(); let mut buffer: Vec<u8> = Vec::new();
match root_dir.open_file(&["/CONFIG/", key, ".BIN"].concat()) { match root_dir.open_file(&["/CONFIG/", key, ".BIN"].concat()) {
Ok(mut f) => f.read_to_end(&mut buffer).map(|_| ())?, Ok(mut f) => f.read(&mut buffer).map(|_| ())?,
Err(_) => match root_dir.open_file("/CONFIG.TXT") { Err(_) => match root_dir.open_file("/CONFIG.TXT") {
Ok(f) => parse_config(key, &mut buffer, f)?, Ok(f) => parse_config(key, &mut buffer, f)?,
Err(_) => return Err(Error::KeyNotFoundError(key)), Err(_) => return Err(Error::KeyNotFoundError(key)),
@ -113,11 +137,11 @@ impl Config {
} }
} }
pub fn read_str<'b>(&self, key: &'b str) -> Result<'b, String> { pub fn read_str<'b>(&'b self, key: &'b str) -> Result<'b, String> {
Ok(String::from_utf8(self.read(key)?)?) Ok(String::from_utf8(self.read(key)?)?)
} }
pub fn remove<'b>(&self, key: &'b str) -> Result<'b, ()> { pub fn remove<'b>(&'b self, key: &'b str) -> Result<'b, ()> {
if let Some(fs) = &self.fs { if let Some(fs) = &self.fs {
let root_dir = fs.root_dir(); let root_dir = fs.root_dir();
match root_dir.remove(&["/CONFIG/", key, ".BIN"].concat()) { match root_dir.remove(&["/CONFIG/", key, ".BIN"].concat()) {
@ -127,18 +151,19 @@ impl Config {
match root_dir.create_file("/CONFIG.TXT") { match root_dir.create_file("/CONFIG.TXT") {
Ok(mut f) => { Ok(mut f) => {
let mut buffer = String::new(); let mut buffer = String::new();
f.read_to_string(&mut buffer)?; read_to_string(&mut f, &mut buffer)?;
f.seek(SeekFrom::Start(0))?; f.seek(SeekFrom::Start(0))?;
f.truncate()?; f.truncate()?;
for line in buffer.lines() { for line in buffer.lines() {
if line.len() > 0 && !line.to_ascii_lowercase().starts_with(&prefix) { if line.len() > 0 && !line.to_ascii_lowercase().starts_with(&prefix)
{
f.write(line.as_bytes())?; f.write(line.as_bytes())?;
f.write(NEWLINE)?; f.write(NEWLINE)?;
} }
} }
Ok(()) Ok(())
}, }
Err(_) => Err(Error::KeyNotFoundError(key)) Err(_) => Err(Error::KeyNotFoundError(key)),
} }
} }
} }
@ -164,7 +189,10 @@ impl Config {
if is_str { if is_str {
let mut f = root_dir.create_file("/CONFIG.TXT")?; let mut f = root_dir.create_file("/CONFIG.TXT")?;
f.seek(SeekFrom::End(0))?; f.seek(SeekFrom::End(0))?;
write!(f, "{}={}\n", key, String::from_utf8(value).unwrap())?; f.write(key.as_bytes());
f.write("=".as_bytes());
f.write(value.as_slice());
f.write(NEWLINE);
} else { } else {
let dir = root_dir.create_dir("/CONFIG")?; let dir = root_dir.create_dir("/CONFIG")?;
let mut f = dir.create_file(&[key, ".BIN"].concat())?; let mut f = dir.create_file(&[key, ".BIN"].concat())?;

View File

@ -1,9 +1,8 @@
use fatfs;
use fatfs::io::{Read, Seek, SeekFrom, Write}
use libboard_zynq::sdio::{sd_card::SdCard, CmdTransferError};
use log::debug;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::fmt; use core::fmt;
use fatfs::{self, IoBase, IoError, Read, Seek, SeekFrom, Write};
use libboard_zynq::sdio::{sd_card::SdCard, CmdTransferError};
use log::debug;
const MBR_SIGNATURE: [u8; 2] = [0x55, 0xAA]; const MBR_SIGNATURE: [u8; 2] = [0x55, 0xAA];
const PARTID_FAT12: u8 = 0x01; const PARTID_FAT12: u8 = 0x01;
@ -17,18 +16,18 @@ const BLOCK_SIZE: usize = 512;
#[derive(Debug)] #[derive(Debug)]
pub struct Error { pub struct Error {
message: String message: &'static str,
} }
impl Error { impl Error {
pub fn new(message: &str) -> Self { pub fn new(message: &'static str) -> Self {
Self { message: String::new(message) } Self { message: message }
} }
} }
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, self.message) write!(f, "{}", self.message)
} }
} }
@ -110,7 +109,7 @@ impl SdReader {
/// Internal read function for unaligned read. /// Internal read function for unaligned read.
/// The read must not cross block boundary. /// The read must not cross block boundary.
fn read_unaligned(&mut self, buf: &mut [u8]) -> Result<usize> { fn read_unaligned(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
if buf.len() == 0 { if buf.len() == 0 {
return Ok(0); return Ok(0);
} }
@ -124,7 +123,7 @@ impl SdReader {
/// Internal write function for unaligned write. /// Internal write function for unaligned write.
/// The write must not cross block boundary. /// The write must not cross block boundary.
fn write_unaligned(&mut self, buf: &[u8]) -> Result<usize> { fn write_unaligned(&mut self, buf: &[u8]) -> Result<usize, Error> {
if buf.len() == 0 { if buf.len() == 0 {
return Ok(0); return Ok(0);
} }
@ -175,7 +174,7 @@ impl SdReader {
} }
/// Set the base offset of the SD card, to transform from physical address to logical address. /// Set the base offset of the SD card, to transform from physical address to logical address.
fn set_base_offset(&mut self, offset: u32) -> Result<u64> { fn set_base_offset(&mut self, offset: u32) -> Result<u64, Error> {
self.offset = offset; self.offset = offset;
self.seek(SeekFrom::Start(0)) self.seek(SeekFrom::Start(0))
} }
@ -183,27 +182,28 @@ impl SdReader {
/// Mount fatfs from partition entry, and return the fatfs object if success. /// Mount fatfs from partition entry, and return the fatfs object if success.
/// This takes the ownership of self, so currently there is no way to recover from an error, /// This takes the ownership of self, so currently there is no way to recover from an error,
/// except creating a new SD card instance. /// except creating a new SD card instance.
pub fn mount_fatfs(mut self, entry: PartitionEntry) -> Result<fatfs::FileSystem<Self>> { pub fn mount_fatfs(
mut self,
entry: PartitionEntry,
) -> Result<fatfs::FileSystem<Self>, fatfs::Error<Error>> {
let mut buffer: [u8; 4] = [0; 4]; let mut buffer: [u8; 4] = [0; 4];
self.seek(SeekFrom::Start(0x1FE))?; self.seek(SeekFrom::Start(0x1FE))?;
self.read_exact(&mut buffer[..2])?; self.read_exact(&mut buffer[..2])?;
// check MBR signature // check MBR signature
if buffer[..2] != MBR_SIGNATURE { if buffer[..2] != MBR_SIGNATURE {
return Err(Error::new( return Err(fatfs::Error::Io(Error::new("Incorrect signature for MBR sector.")));
"Incorrect signature for MBR sector.",
));
} }
// Read partition ID. // Read partition ID.
self.seek(SeekFrom::Start(entry as u64 + 0x4))?; self.seek(SeekFrom::Start(entry as u64 + 0x4))?;
self.read_exact(&mut buffer[..1])?; self.read_exact(&mut buffer[..1])?;
debug!("Partition ID: {:0X}", buffer[0]); debug!("Partition ID: {:0X}", buffer[0]);
match buffer[0] { match buffer[0] {
PARTID_FAT12 | PARTID_FAT16_LESS32M | PARTID_FAT16 | PARTID_FAT12 | PARTID_FAT16_LESS32M | PARTID_FAT16 | PARTID_FAT16_LBA
PARTID_FAT16_LBA | PARTID_FAT32 | PARTID_FAT32_LBA => {} | PARTID_FAT32 | PARTID_FAT32_LBA => {}
_ => { _ => {
return Err(Error::new( return Err(fatfs::Error::Io(Error::new(
"No FAT partition found for the specified entry.", "No FAT partition found for the specified entry.",
)); )));
} }
} }
// Read LBA // Read LBA
@ -219,6 +219,25 @@ impl SdReader {
// setup fatfs // setup fatfs
fatfs::FileSystem::new(self, fatfs::FsOptions::new()) fatfs::FileSystem::new(self, fatfs::FsOptions::new())
} }
fn fill_buf(&mut self) -> Result<&[u8], Error> {
if self.index == BLOCK_SIZE {
// flush the buffer if it is dirty before overwriting it with new data
if self.dirty {
self.flush()?;
}
// reload buffer
self.sd
.read_block(self.byte_addr / (BLOCK_SIZE as u32), 1, &mut self.buffer)?;
self.index = (self.byte_addr as usize) % BLOCK_SIZE;
}
Ok(&self.buffer[self.index..])
}
fn consume(&mut self, amt: usize) {
self.index += amt;
self.byte_addr += amt as u32;
}
} }
impl Read for SdReader { impl Read for SdReader {
@ -272,8 +291,7 @@ impl Write for SdReader {
fn flush(&mut self) -> Result<(), Error> { fn flush(&mut self) -> Result<(), Error> {
if self.dirty { if self.dirty {
let block_addr = (self.byte_addr - self.index as u32) / (BLOCK_SIZE as u32); let block_addr = (self.byte_addr - self.index as u32) / (BLOCK_SIZE as u32);
self.sd self.sd.write_block(block_addr, 1, &self.buffer)?;
.write_block(block_addr, 1, &self.buffer)?;
self.dirty = false; self.dirty = false;
} }
Ok(()) Ok(())

View File

@ -8,7 +8,7 @@ mod netboot;
use alloc::rc::Rc; use alloc::rc::Rc;
use core::mem; use core::mem;
use fatfs::io::{Read, Seek}; use fatfs::{self, DefaultTimeProvider, LossyOemCpConverter, Read, Seek};
use libboard_zynq::{ use libboard_zynq::{
self as zynq, self as zynq,
clocks::source::{ArmPll, ClockSource, IoPll}, clocks::source::{ArmPll, ClockSource, IoPll},
@ -16,7 +16,7 @@ use libboard_zynq::{
logger, println, sdio, slcr, logger, println, sdio, slcr,
timer::GlobalTimer, timer::GlobalTimer,
}; };
use libconfig::{bootgen, sd_reader, Config}; use libconfig::{bootgen, sd_reader, Config, File};
use libcortex_a9::{ use libcortex_a9::{
asm::{dsb, isb}, asm::{dsb, isb},
cache::{bpiall, dcciall, iciallu}, cache::{bpiall, dcciall, iciallu},
@ -30,8 +30,8 @@ extern "C" {
static mut __runtime_end: usize; static mut __runtime_end: usize;
} }
fn boot_sd<File: Read + Seek>( fn boot_sd<'a>(
file: &mut Option<File>, file: &mut Option<File<'a>>,
runtime_start: *mut u8, runtime_start: *mut u8,
runtime_max: usize, runtime_max: usize,
) -> Result<(), ()> { ) -> Result<(), ()> {

View File

@ -1,7 +1,7 @@
use alloc::vec; use alloc::vec;
use alloc::vec::Vec; use alloc::vec::Vec;
use byteorder::{ByteOrder, NetworkEndian}; use byteorder::{ByteOrder, NetworkEndian};
use fatfs::io::{Read, Seek}; use fatfs::{Read, Seek};
use libboard_zynq::{ use libboard_zynq::{
devc, devc,
eth::Eth, eth::Eth,
@ -13,7 +13,7 @@ use libboard_zynq::{
}, },
timer::GlobalTimer, timer::GlobalTimer,
}; };
use libconfig::{bootgen, net_settings, Config}; use libconfig::{bootgen, net_settings, Config, File};
enum NetConnState { enum NetConnState {
WaitCommand, WaitCommand,
@ -48,7 +48,7 @@ impl NetConn {
self.gateware_downloaded = false; self.gateware_downloaded = false;
} }
fn input_partial<File: Read + Seek>( fn input_partial(
&mut self, &mut self,
bootgen_file: &mut Option<File>, bootgen_file: &mut Option<File>,
runtime_start: *mut u8, runtime_start: *mut u8,
@ -284,9 +284,9 @@ impl NetConn {
} }
} }
fn input<File: Read + Seek>( fn input<'a>(
&mut self, &mut self,
bootgen_file: &mut Option<File>, bootgen_file: &mut Option<File<'a>>,
runtime_start: *mut u8, runtime_start: *mut u8,
runtime_max_len: usize, runtime_max_len: usize,
buf: &[u8], buf: &[u8],
@ -309,8 +309,8 @@ impl NetConn {
} }
} }
pub fn netboot<File: Read + Seek>( pub fn netboot<'a>(
bootgen_file: &mut Option<File>, bootgen_file: &mut Option<File<'a>>,
cfg: Config, cfg: Config,
runtime_start: *mut u8, runtime_start: *mut u8,
runtime_max_len: usize, runtime_max_len: usize,