Skip to content

Commit 6dd21a2

Browse files
anthonychen1251pamaury
authored andcommitted
[rescue,test] Add functional tests for Get{DeviceId,BootLog} commands
This introduces the tests to verify the functionality of the `GetDeviceId` and `GetBootLog` rescue commands. The `get_device_id_test` verifies the retrieved DeviceId against OTP configuration; `get_boot_log_test` validates some BootLog fields against the ROM_EXT manifest. Signed-off-by: Anthony Chen <[email protected]> (cherry picked from commit f4c325c)
1 parent 2bc07ad commit 6dd21a2

File tree

9 files changed

+257
-2
lines changed

9 files changed

+257
-2
lines changed

sw/device/silicon_creator/rom_ext/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ ROM_EXT_FEATURES = [
254254
testonly = True,
255255
ecdsa_key = {"//sw/device/silicon_creator/rom/keys/fake/ecdsa:prod_key_0_ecdsa_p256": "prod_key_0"},
256256
exec_env = [
257+
"//hw/top_earlgrey:fpga_cw340",
257258
"//hw/top_earlgrey:fpga_cw310",
258259
"//hw/top_earlgrey:fpga_cw340",
259260
],

sw/device/silicon_creator/rom_ext/e2e/BUILD

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ load(
1414
"otp_json",
1515
"otp_partition",
1616
)
17+
load(
18+
"//sw/device/silicon_creator/rom_ext/e2e:defs.bzl",
19+
"DEVICE_ID",
20+
)
1721

1822
package(default_visibility = ["//visibility:public"])
1923

@@ -34,7 +38,7 @@ otp_json(
3438
otp_partition(
3539
name = "HW_CFG0",
3640
items = {
37-
"DEVICE_ID": "0000000011111111222222223333333344444444555555556666666600010001",
41+
"DEVICE_ID": DEVICE_ID,
3842
},
3943
lock = True,
4044
),

sw/device/silicon_creator/rom_ext/e2e/defs.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ OWNER_SLOTS = {
66
"a": "{owner_slot_a}",
77
"b": "{owner_slot_b}",
88
}
9+
10+
DEVICE_ID = "0000000011111111222222223333333344444444555555556666666600010001"

sw/device/silicon_creator/rom_ext/e2e/ownership/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ opentitan_binary(
3131
},
3232
exec_env = {
3333
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
34+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
3435
},
3536
deps = [
3637
"//sw/device/lib/base:status",
@@ -51,6 +52,7 @@ opentitan_binary(
5152
},
5253
exec_env = {
5354
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
55+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
5456
},
5557
linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_owner_slot_virtual",
5658
deps = [
@@ -629,6 +631,7 @@ opentitan_binary(
629631
},
630632
exec_env = {
631633
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
634+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
632635
},
633636
deps = [
634637
"//hw/top_earlgrey/sw/autogen:top_earlgrey",

sw/device/silicon_creator/rom_ext/e2e/ownership/defs.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ def ownership_transfer_test(
1212
srcs = ["//sw/device/silicon_creator/rom_ext/e2e/verified_boot:boot_test"],
1313
exec_env = {
1414
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
15+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
1516
},
1617
ecdsa_key = {
1718
"//sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_ecdsa": "app_prod",

sw/device/silicon_creator/rom_ext/e2e/rescue/BUILD

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ load(
1414
"opentitan_binary",
1515
"opentitan_test",
1616
)
17+
load(
18+
"//sw/device/silicon_creator/rom_ext/e2e:defs.bzl",
19+
"DEVICE_ID",
20+
)
1721

1822
package(default_visibility = ["//visibility:public"])
1923

@@ -303,6 +307,7 @@ opentitan_test(
303307
],
304308
exec_env = {
305309
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
310+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
306311
},
307312
fpga = fpga_params(
308313
changes_otp = True,
@@ -374,6 +379,7 @@ opentitan_test(
374379
],
375380
exec_env = {
376381
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
382+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
377383
},
378384
fpga = fpga_params(
379385
changes_otp = True,
@@ -409,6 +415,7 @@ opentitan_test(
409415
],
410416
exec_env = {
411417
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
418+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
412419
},
413420
fpga = fpga_params(
414421
changes_otp = True,
@@ -439,6 +446,7 @@ opentitan_test(
439446
name = "rescue_enter_on_fail_{}".format(name),
440447
exec_env = {
441448
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
449+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
442450
},
443451
fpga = fpga_params(
444452
assemble = "",
@@ -465,3 +473,49 @@ opentitan_test(
465473
)
466474
for name, config in _CONFIGS.items()
467475
]
476+
477+
[
478+
opentitan_test(
479+
name = "rescue_get_boot_log_{}".format(protocol),
480+
exec_env = {
481+
"//hw/top_earlgrey:fpga_hyper310_rom_ext": None,
482+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
483+
},
484+
fpga = fpga_params(
485+
assemble = "",
486+
params = config["params"],
487+
rom_ext = config["rom_ext"],
488+
test_cmd = """
489+
--clear-bitstream
490+
--bootstrap={rom_ext}
491+
rescue {params} --action=get-boot-log
492+
""",
493+
test_harness = "//sw/host/tests/rescue:rescue_test",
494+
),
495+
)
496+
for protocol, config in _CONFIGS.items()
497+
]
498+
499+
[
500+
opentitan_test(
501+
name = "rescue_get_device_id_{}".format(protocol),
502+
exec_env = {
503+
"//hw/top_earlgrey:fpga_hyper310_rom_ext": None,
504+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
505+
},
506+
fpga = fpga_params(
507+
assemble = "",
508+
device_id = DEVICE_ID,
509+
params = config["params"],
510+
rom_ext = config["rom_ext"],
511+
test_cmd = """
512+
--clear-bitstream
513+
--bootstrap={rom_ext}
514+
--device-id={device_id}
515+
rescue {params} --action=get-device-id
516+
""",
517+
test_harness = "//sw/host/tests/rescue:rescue_test",
518+
),
519+
)
520+
for protocol, config in _CONFIGS.items()
521+
]

sw/host/opentitanlib/src/chip/device_id.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
77
use serde_annotate::Annotate;
88
use std::io::{Read, Write};
99

10-
#[derive(Debug, Default, Annotate)]
10+
#[derive(Debug, Default, Annotate, PartialEq, Eq)]
1111
pub struct DeviceId {
1212
#[annotate(format=hex)]
1313
pub creator: u16,

sw/host/tests/rescue/BUILD

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,15 @@ rust_binary(
3131
"@crate_index//:log",
3232
],
3333
)
34+
35+
rust_binary(
36+
name = "rescue_test",
37+
srcs = ["rescue_test.rs"],
38+
deps = [
39+
"//sw/host/opentitanlib",
40+
"@crate_index//:anyhow",
41+
"@crate_index//:clap",
42+
"@crate_index//:hex",
43+
"@crate_index//:humantime",
44+
],
45+
)
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#![allow(clippy::bool_assert_comparison)]
6+
use anyhow::{Context, Result, anyhow};
7+
use clap::{Args, Parser, Subcommand, ValueEnum};
8+
9+
use std::io::Cursor;
10+
use std::path::Path;
11+
use std::time::Duration;
12+
13+
use opentitanlib::app::TransportWrapper;
14+
use opentitanlib::chip::boot_log::OwnershipState;
15+
use opentitanlib::chip::boot_svc::BootSlot;
16+
use opentitanlib::chip::device_id::DeviceId;
17+
use opentitanlib::image::image::{self};
18+
use opentitanlib::rescue::{EntryMode, RescueParams};
19+
use opentitanlib::test_utils::init::InitializeTest;
20+
use opentitanlib::util::file::FromReader;
21+
22+
#[derive(Debug, Parser)]
23+
struct Opts {
24+
#[command(flatten)]
25+
init: InitializeTest,
26+
27+
#[command(subcommand)]
28+
command: Commands,
29+
30+
// Device ID represented as a hexadecimal string.
31+
// This format should correspond to how the ID is structured or stored
32+
// in the device's OTP.
33+
#[arg(long)]
34+
device_id: Option<String>,
35+
36+
/// Console receive timeout.
37+
#[arg(long, value_parser = humantime::parse_duration, default_value = "10s")]
38+
timeout: Duration,
39+
}
40+
41+
#[derive(Clone, Debug, Args)]
42+
struct RescueCommand {
43+
#[command(flatten)]
44+
params: RescueParams,
45+
46+
#[arg(long)]
47+
action: RescueTestActions,
48+
}
49+
50+
#[derive(Debug, Subcommand)]
51+
enum Commands {
52+
Rescue(RescueCommand),
53+
}
54+
55+
#[derive(ValueEnum, Debug, Clone, Copy, PartialEq)]
56+
pub enum RescueTestActions {
57+
GetDeviceId,
58+
GetBootLog,
59+
}
60+
61+
fn get_device_id_test(
62+
expected_device_id_hex: &String,
63+
params: &RescueParams,
64+
transport: &TransportWrapper,
65+
) -> Result<()> {
66+
let rescue = params.create(transport)?;
67+
rescue.enter(transport, EntryMode::Reset)?;
68+
let actual_device_id_from_rescue = rescue.get_device_id()?;
69+
let mut bytes_from_hex = hex::decode(expected_device_id_hex).map_err(|e| {
70+
anyhow!(
71+
"Failed to decode hex string '{}': {}",
72+
expected_device_id_hex,
73+
e
74+
)
75+
})?;
76+
// This reversal is to swap the byte order of the entire decoded hex sequence
77+
// to match the endianness expectation of the DeviceId::read function.
78+
bytes_from_hex.reverse();
79+
let mut cursor = Cursor::new(bytes_from_hex);
80+
let parsed_expected_device_id = DeviceId::read(&mut cursor).unwrap();
81+
if parsed_expected_device_id == actual_device_id_from_rescue {
82+
Ok(())
83+
} else {
84+
Err(anyhow!(
85+
"Device ID mismatch. Expected: {:?}, but got: {:?}",
86+
parsed_expected_device_id,
87+
actual_device_id_from_rescue
88+
))
89+
}
90+
}
91+
92+
fn get_boot_log_test(
93+
binary: &Path,
94+
params: &RescueParams,
95+
transport: &TransportWrapper,
96+
) -> Result<()> {
97+
const BOOT_LOG_IDENTIFIER: u32 = u32::from_le_bytes(*b"BLOG");
98+
let image = image::Image::read_from_file(binary)?;
99+
let rescue = params.create(transport)?;
100+
rescue.enter(transport, EntryMode::Reset)?;
101+
let boot_log = rescue
102+
.get_boot_log()
103+
.context("Failed to get boot log from rescue")?;
104+
let rom_ext_manifest = image
105+
.subimages()?
106+
.get(0)
107+
.ok_or_else(|| anyhow!("No subimages found in the image"))?
108+
.manifest;
109+
if boot_log.rom_ext_major != rom_ext_manifest.version_major {
110+
return Err(anyhow!(
111+
"rom_ext_major mismatch. Expected: {}, but got: {}",
112+
rom_ext_manifest.version_major,
113+
boot_log.rom_ext_major
114+
));
115+
}
116+
117+
if boot_log.rom_ext_minor != rom_ext_manifest.version_minor {
118+
return Err(anyhow!(
119+
"rom_ext_minor mismatch. Expected: {}, but got: {}",
120+
rom_ext_manifest.version_minor,
121+
boot_log.rom_ext_minor
122+
));
123+
}
124+
125+
if boot_log.ownership_state != OwnershipState::LockedOwner {
126+
return Err(anyhow!(
127+
"ownership_state mismatch. Expected: {}, but got: {}",
128+
OwnershipState::LockedOwner,
129+
boot_log.ownership_state
130+
));
131+
}
132+
133+
if boot_log.identifier != BOOT_LOG_IDENTIFIER {
134+
return Err(anyhow!(
135+
"identifier mismatch. Expected: {}, but got: {}",
136+
BOOT_LOG_IDENTIFIER,
137+
boot_log.identifier
138+
));
139+
}
140+
141+
if boot_log.rom_ext_slot != BootSlot::SlotA {
142+
return Err(anyhow!(
143+
"rom_ext_slot mismatch. Expected: {}, but got: {}",
144+
BootSlot::SlotA,
145+
boot_log.rom_ext_slot
146+
));
147+
}
148+
149+
Ok(())
150+
}
151+
152+
fn main() -> Result<()> {
153+
let opts = Opts::parse();
154+
opts.init.init_logging();
155+
let transport = opts.init.init_target()?;
156+
157+
match opts.command {
158+
Commands::Rescue(rescue) => match rescue.action {
159+
RescueTestActions::GetDeviceId => {
160+
let device_id = &opts
161+
.device_id
162+
.as_ref()
163+
.ok_or_else(|| anyhow!("No device_id provided"))?;
164+
get_device_id_test(device_id, &rescue.params, &transport)?;
165+
}
166+
RescueTestActions::GetBootLog => {
167+
let binary = &opts
168+
.init
169+
.bootstrap
170+
.bootstrap
171+
.as_ref()
172+
.ok_or_else(|| anyhow!("No RV32 test binary provided"))?;
173+
get_boot_log_test(binary, &rescue.params, &transport)?;
174+
}
175+
},
176+
}
177+
Ok(())
178+
}

0 commit comments

Comments
 (0)