// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#![deny(warnings)]

use libc;
use std::fs::{File, OpenOptions};
use std::io::{Error, ErrorKind, Read, Seek, SeekFrom, Write};
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;
use structopt::StructOpt;

const PCI_DIR: &str = "/dev/disk/by-path";

#[cfg(target_arch = "aarch64")]
const PCI_DEVICE: &str = "platform-808100000.pci-pci-0000";

#[cfg(target_arch = "x86_64")]
const PCI_DEVICE: &str = "virtio-pci-0000";

// Ioctl requests are comprised of 32 bits:
// [31:30]  Access mode
// [29:16]  Size of the parameter structure
// [15:8]   Request type
// [7:0]    Request number
// For the ioctls we care about here there are no parameters, so we set only a type and a number.
// See Linux:include/uapi/asm-generic/ioctl.h for more details.
const TYPE_SHIFT: usize = 8;
macro_rules! define_ioctl {
    ($name:ident, $typ:expr, $num:expr, $return_type:ty) => {
        fn $name(file: &File) -> $return_type {
            let request = ($typ << TYPE_SHIFT) | ($num & 0xff);
            let mut r: $return_type = 0;
            unsafe {
                libc::ioctl(file.as_raw_fd(), request, &mut r);
            }
            r
        }
    };
}

// Block ioctl types and number are defined in Linux:include/uapi/linux/fs.h.
define_ioctl!(block_dev_size, 0x12, 96, u64);
define_ioctl!(block_dev_sector_size, 0x12, 104, u32);

#[derive(StructOpt, Debug)]
struct Config {
    block_size: u32,
    pci_bus: u8,
    pci_device: u8,
    #[structopt(subcommand)]
    cmd: Command,
}

#[derive(StructOpt, Debug)]
enum Command {
    #[structopt(name = "check")]
    Check { block_count: u64 },
    #[structopt(name = "read")]
    Read { offset: u64, expected: u8 },
    #[structopt(name = "write")]
    Write { offset: u64, value: u8 },
}

fn open_block_device(pci_bus: u8, pci_device: u8, write: bool) -> std::io::Result<File> {
    let mut path = PathBuf::from(PCI_DIR);
    path.push(format!(
        "{}:{:02}:{:02}.0", PCI_DEVICE, pci_bus, pci_device
    ));
    OpenOptions::new().read(true).write(write).open(path)
}

fn check(block_dev: &File, block_size: u32, block_count: u64) -> std::io::Result<()> {
    let actual_block_size = block_dev_sector_size(block_dev);
    let actual_block_count = block_dev_size(block_dev);

    if block_size != actual_block_size {
        return Err(Error::new(
            ErrorKind::Other,
            format!(
                "Incorrect size: {} (expected {}).",
                actual_block_size, block_size
            ),
        ));
    }
    if block_count != actual_block_count {
        return Err(Error::new(
            ErrorKind::Other,
            format!(
                "Incorrect count: {} (expected {}).",
                actual_block_count, block_count
            ),
        ));
    }
    Ok(())
}

fn read_block(
    block_dev: &mut File,
    block_size: u32,
    offset: u64,
    expected: u8,
) -> std::io::Result<()> {
    block_dev.seek(SeekFrom::Start(offset * u64::from(block_size)))?;
    let mut data: Vec<u8> = vec![0; block_size as usize];
    block_dev.read_exact(&mut data)?;
    if !data.iter().all(|&b| b == expected) {
        return Err(Error::new(ErrorKind::Other, "Incorrect data read"));
    }
    Ok(())
}

fn write_block(
    block_dev: &mut File,
    block_size: u32,
    offset: u64,
    value: u8,
) -> std::io::Result<()> {
    block_dev.seek(SeekFrom::Start(offset * u64::from(block_size)))?;
    let data: Vec<u8> = vec![value; block_size as usize];
    block_dev.write_all(&data)?;
    block_dev.sync_all()?;
    Ok(())
}

fn main() -> std::io::Result<()> {
    let config = Config::from_args();
    let write = if let Command::Write { .. } = config.cmd {
        true
    } else {
        false
    };
    let mut block_dev = open_block_device(config.pci_bus, config.pci_device, write)?;
    let result = match config.cmd {
        Command::Check { block_count } => check(&block_dev, config.block_size, block_count),
        Command::Read { offset, expected } => {
            read_block(&mut block_dev, config.block_size, offset, expected)
        }
        Command::Write { offset, value } => {
            write_block(&mut block_dev, config.block_size, offset, value)
        }
    };
    if result.is_ok() {
        println!("PASS");
    }
    result
}
