forked from M-Labs/zynq-rs
up rust-fatfs to 0.4, remove core_io
This commit is contained in:
parent
aef7dcabae
commit
6dc831a8f8
|
@ -112,7 +112,12 @@
|
||||||
src = builtins.filterSource (path: type:
|
src = builtins.filterSource (path: type:
|
||||||
baseNameOf path != "target"
|
baseNameOf path != "target"
|
||||||
) ./.;
|
) ./.;
|
||||||
cargoLock = { lockFile = ./Cargo.lock; };
|
cargoLock = {
|
||||||
|
lockFile = ./Cargo.lock;
|
||||||
|
outputHashes = {
|
||||||
|
"fatfs-0.4.0" = "sha256-P7IgvhwTPXtNhcyv8cFqwO2UdaEcCGJY7UBG6+yBFSg=";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ cargo-xbuild llvmPackages_11.clang-unwrapped ];
|
nativeBuildInputs = [ cargo-xbuild llvmPackages_11.clang-unwrapped ];
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
|
|
|
@ -6,10 +6,14 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libboard_zynq = { path = "../libboard_zynq" }
|
libboard_zynq = { path = "../libboard_zynq" }
|
||||||
core_io = { version = "0.1", features = ["collections"] }
|
|
||||||
fatfs = { version = "0.3", features = ["core_io"], default-features = false }
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
|
[dependencies.fatfs]
|
||||||
|
git = "https://github.com/rafalh/rust-fatfs"
|
||||||
|
rev = "85f06e0"
|
||||||
|
default-features = false
|
||||||
|
features = ["alloc", "lfn"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = []
|
target_zc706 = []
|
||||||
target_coraz7 = []
|
target_coraz7 = []
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core_io::{Error, Read, Seek, SeekFrom};
|
use fatfs::{self, 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,
|
||||||
|
@ -58,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;
|
||||||
|
@ -69,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)?;
|
||||||
|
@ -82,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)?;
|
||||||
|
@ -98,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))?;
|
||||||
|
@ -149,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
|
||||||
|
@ -170,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 {
|
||||||
|
|
|
@ -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, Read, Seek, SeekFrom, Write};
|
||||||
use core_io::{self as io, BufRead, BufReader, 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(io::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<io::Error> for Error<'a> {
|
impl<'a> From<SdReadError> for Error<'a> {
|
||||||
fn from(error: io::Error) -> Self {
|
fn from(error: SdReadError) -> Self {
|
||||||
Error::IoError(error)
|
Error::IoError(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,14 +56,36 @@ impl<'a> From<FromUtf8Error> for Error<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simplified replacements to `read_to_end` and `read_to_string` from core_io
|
||||||
|
fn read_to_end<'a>(file: &mut File<'a>, buffer: &mut Vec<u8>) -> Result<'a, ()> {
|
||||||
|
let mut temp_buffer = [0; 1024];
|
||||||
|
loop {
|
||||||
|
let read_bytes = file.read(&mut temp_buffer)?;
|
||||||
|
if read_bytes == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer.extend_from_slice(&temp_buffer[..read_bytes]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_to_string<'a>(file: &mut File<'a>) -> Result<'a, String> {
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
read_to_end(file, &mut buffer)?;
|
||||||
|
Ok(String::from_utf8(buffer)?)
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
||||||
for line in BufReader::new(file).lines() {
|
let read_buffer = read_to_string(&mut file)?;
|
||||||
let line = line?.to_ascii_lowercase();
|
for line in read_buffer.lines() {
|
||||||
|
let line = line.to_ascii_lowercase();
|
||||||
if line.starts_with(&prefix) {
|
if line.starts_with(&prefix) {
|
||||||
buffer.extend(line[prefix.len()..].as_bytes());
|
buffer.extend(line[prefix.len()..].as_bytes());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -83,7 +110,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 {
|
||||||
|
@ -94,12 +123,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) => read_to_end( &mut f, &mut buffer)?,
|
||||||
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)),
|
||||||
|
@ -111,11 +140,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()) {
|
||||||
|
@ -124,19 +153,19 @@ impl Config {
|
||||||
let prefix = [key, "="].concat().to_ascii_lowercase();
|
let prefix = [key, "="].concat().to_ascii_lowercase();
|
||||||
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 buffer = read_to_string(&mut f)?;
|
||||||
f.read_to_string(&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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +191,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())?;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use core_io::{BufRead, Error, ErrorKind, Read, Result as IoResult, Seek, SeekFrom, Write};
|
use alloc::vec::Vec;
|
||||||
use fatfs;
|
use core::fmt;
|
||||||
|
use fatfs::{self, IoBase, IoError, Read, Seek, SeekFrom, Write};
|
||||||
use libboard_zynq::sdio::{sd_card::SdCard, CmdTransferError};
|
use libboard_zynq::sdio::{sd_card::SdCard, CmdTransferError};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
const MBR_SIGNATURE: [u8; 2] = [0x55, 0xAA];
|
const MBR_SIGNATURE: [u8; 2] = [0x55, 0xAA];
|
||||||
const PARTID_FAT12: u8 = 0x01;
|
const PARTID_FAT12: u8 = 0x01;
|
||||||
|
@ -12,13 +12,46 @@ const PARTID_FAT32: u8 = 0x0B;
|
||||||
const PARTID_FAT32_LBA: u8 = 0x0C;
|
const PARTID_FAT32_LBA: u8 = 0x0C;
|
||||||
const PARTID_FAT16_LBA: u8 = 0x0E;
|
const PARTID_FAT16_LBA: u8 = 0x0E;
|
||||||
|
|
||||||
fn cmd_error_to_io_error(_: CmdTransferError) -> Error {
|
|
||||||
Error::new(ErrorKind::Other, "Command transfer error")
|
|
||||||
}
|
|
||||||
|
|
||||||
const BLOCK_SIZE: usize = 512;
|
const BLOCK_SIZE: usize = 512;
|
||||||
|
|
||||||
/// SdReader struct implementing `Read + BufRead + Write + Seek` traits for `core_io`.
|
#[derive(Debug)]
|
||||||
|
pub struct Error {
|
||||||
|
message: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub fn new(message: &'static str) -> Self {
|
||||||
|
Self { message: message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IoError for Error {
|
||||||
|
fn is_interrupted(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_unexpected_eof_error() -> Self {
|
||||||
|
Error::new("Unexpected end of file error")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_write_zero_error() -> Self {
|
||||||
|
Error::new("Write zero error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CmdTransferError> for Error {
|
||||||
|
fn from(_: CmdTransferError) -> Self {
|
||||||
|
Error::new("Command transfer error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SdReader struct implementing `Read + Write + Seek` traits for `core_io`.
|
||||||
/// Used as an adaptor for fatfs crate, but could be used directly for raw data access.
|
/// Used as an adaptor for fatfs crate, but could be used directly for raw data access.
|
||||||
///
|
///
|
||||||
/// Implementation: all read/writes would be split into unaligned and block-aligned parts,
|
/// Implementation: all read/writes would be split into unaligned and block-aligned parts,
|
||||||
|
@ -43,6 +76,10 @@ pub struct SdReader {
|
||||||
offset: u32,
|
offset: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IoBase for SdReader {
|
||||||
|
type Error = Error;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
// Partition entry enum, normally we would use entry1.
|
// Partition entry enum, normally we would use entry1.
|
||||||
|
@ -72,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]) -> IoResult<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);
|
||||||
}
|
}
|
||||||
|
@ -86,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]) -> IoResult<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);
|
||||||
}
|
}
|
||||||
|
@ -137,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) -> IoResult<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))
|
||||||
}
|
}
|
||||||
|
@ -145,29 +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) -> IoResult<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.")));
|
||||||
ErrorKind::InvalidData,
|
|
||||||
"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(
|
||||||
ErrorKind::InvalidData,
|
|
||||||
"No FAT partition found for the specified entry.",
|
"No FAT partition found for the specified entry.",
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Read LBA
|
// Read LBA
|
||||||
|
@ -183,10 +219,29 @@ 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 {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
let total_length = buf.len();
|
let total_length = buf.len();
|
||||||
let (a, b, c) = self.block_align_mut(buf);
|
let (a, b, c) = self.block_align_mut(buf);
|
||||||
self.read_unaligned(a)?;
|
self.read_unaligned(a)?;
|
||||||
|
@ -211,30 +266,8 @@ impl Read for SdReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufRead for SdReader {
|
|
||||||
fn fill_buf(&mut self) -> IoResult<&[u8]> {
|
|
||||||
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)
|
|
||||||
.map_err(cmd_error_to_io_error)?;
|
|
||||||
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 Write for SdReader {
|
impl Write for SdReader {
|
||||||
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
|
fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
|
||||||
let (a, b, c) = self.block_align(buf);
|
let (a, b, c) = self.block_align(buf);
|
||||||
self.write_unaligned(a)?;
|
self.write_unaligned(a)?;
|
||||||
if b.len() > 0 {
|
if b.len() > 0 {
|
||||||
|
@ -255,12 +288,10 @@ impl Write for SdReader {
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> IoResult<()> {
|
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)
|
|
||||||
.map_err(cmd_error_to_io_error)?;
|
|
||||||
self.dirty = false;
|
self.dirty = false;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -268,14 +299,14 @@ impl Write for SdReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Seek for SdReader {
|
impl Seek for SdReader {
|
||||||
fn seek(&mut self, pos: SeekFrom) -> IoResult<u64> {
|
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error> {
|
||||||
let raw_target = match pos {
|
let raw_target = match pos {
|
||||||
SeekFrom::Start(x) => self.offset as i64 + x as i64,
|
SeekFrom::Start(x) => self.offset as i64 + x as i64,
|
||||||
SeekFrom::Current(x) => self.byte_addr as i64 + x,
|
SeekFrom::Current(x) => self.byte_addr as i64 + x,
|
||||||
SeekFrom::End(_) => panic!("SD card does not support seek from end"),
|
SeekFrom::End(_) => panic!("SD card does not support seek from end"),
|
||||||
};
|
};
|
||||||
if raw_target < self.offset as i64 || raw_target > core::u32::MAX as i64 {
|
if raw_target < self.offset as i64 || raw_target > core::u32::MAX as i64 {
|
||||||
return Err(Error::new(ErrorKind::InvalidInput, "Invalid address"));
|
return Err(Error::new("Invalid address"));
|
||||||
}
|
}
|
||||||
let target_byte_addr = raw_target as u32;
|
let target_byte_addr = raw_target as u32;
|
||||||
let address_same_block =
|
let address_same_block =
|
||||||
|
|
|
@ -16,10 +16,15 @@ default = ["target_zc706"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
byteorder = { version = "1.3", default-features = false }
|
byteorder = { version = "1.3", default-features = false }
|
||||||
core_io = { version = "0.1", features = ["collections"] }
|
|
||||||
|
|
||||||
libboard_zynq = { path = "../libboard_zynq" }
|
libboard_zynq = { path = "../libboard_zynq" }
|
||||||
libsupport_zynq = { path = "../libsupport_zynq" }
|
libsupport_zynq = { path = "../libsupport_zynq" }
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
libregister = { path = "../libregister" }
|
libregister = { path = "../libregister" }
|
||||||
libconfig = { path = "../libconfig" }
|
libconfig = { path = "../libconfig" }
|
||||||
|
|
||||||
|
[dependencies.fatfs]
|
||||||
|
git = "https://github.com/rafalh/rust-fatfs"
|
||||||
|
rev = "85f06e0"
|
||||||
|
default-features = false
|
||||||
|
features = ["alloc", "lfn"]
|
||||||
|
|
|
@ -8,7 +8,6 @@ mod netboot;
|
||||||
|
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core_io::{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 +15,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 +29,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<(), ()> {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use byteorder::{ByteOrder, NetworkEndian};
|
use byteorder::{ByteOrder, NetworkEndian};
|
||||||
use core_io::{Read, Seek};
|
|
||||||
use libboard_zynq::{
|
use libboard_zynq::{
|
||||||
devc,
|
devc,
|
||||||
eth::Eth,
|
eth::Eth,
|
||||||
|
@ -13,7 +12,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 +47,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 +283,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 +308,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,
|
||||||
|
|
Loading…
Reference in New Issue