1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2021 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.

pub mod bridge;
pub mod capability;
pub mod config;
pub mod db;
pub mod device;
pub mod filter;
pub mod util;

fn u64_from_maybe_hex_str(s: &str) -> Result<u64, String> {
    let (s, radix) = if let Some(s) = s.strip_prefix("0x") { (s, 16) } else { (s, 10) };

    u64::from_str_radix(&s, radix).map_err(|e| e.to_string())
}

use argh::FromArgs;
#[derive(FromArgs, Default)]
/// Display PCI information
pub struct Args {
    #[argh(positional)]
    /// [[<bus>]:][slot][.[<func>]]    Show only devices in selected slots
    pub filter: Option<filter::Filter>,

    #[argh(option, default = "String::from(\"/dev/sys/platform/pt/\")")]
    /// path to the parent directory of the fuchsia.hardware.pci service
    pub service: String,

    #[argh(switch, short = 'v')]
    /// print verbose device configuration
    pub verbose: bool,

    #[argh(switch, short = 'q')]
    /// don't print errors found trying to parse the database
    pub quiet: bool,

    #[argh(switch, short = 'x')]
    /// dump raw configuration space
    pub print_config: bool,

    #[argh(switch, short = 'n')]
    /// print numeric IDs.
    pub print_numeric: bool,

    #[argh(switch, short = 'N')]
    /// only print numeric IDs.
    pub only_print_numeric: bool,

    #[argh(subcommand)]
    pub command: Option<SubCommand>,
}

#[derive(Copy, Clone, FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
pub enum SubCommand {
    Buses(BusesCommand),
    Read(ReadBarCommand),
}

/// List PCI buses found in the system.
#[derive(Copy, Clone, FromArgs, PartialEq, Default, Debug)]
#[argh(subcommand, name = "buses")]
pub struct BusesCommand {}

/// Read from an MMIO BAR of a specified device.
/// For example, to read from BAR 2 of device at address 00:01.0:
///   lspci read 00:01.0 2
#[derive(Copy, Clone, FromArgs, PartialEq, Default, Debug)]
#[argh(subcommand, name = "read")]
pub struct ReadBarCommand {
    /// device address in BDF format BB:DD.F.
    #[argh(positional)]
    pub device: filter::Filter,
    /// BAR id to read from.
    #[argh(positional)]
    pub bar_id: u8,
    /// offset into the BAR to read [default = 0x0].
    #[argh(option, short = 'o', default = "0", from_str_fn(u64_from_maybe_hex_str))]
    pub offset: u64,
    /// how much to read [default = 0x80].
    #[argh(option, short = 's', default = "128", from_str_fn(u64_from_maybe_hex_str))]
    pub size: u64,
    /// print verbose read information
    #[argh(switch, short = 'v')]
    pub verbose: bool,
}