Skip to content

Commit

Permalink
Merge pull request betrusted-io#270 from gsora/feat/pddb-init-notific…
Browse files Browse the repository at this point in the history
…ation

feat: show boot process notifications for PDDB
  • Loading branch information
bunnie authored Nov 5, 2022
2 parents 4264231 + 817e758 commit fa90e74
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 47 deletions.
2 changes: 2 additions & 0 deletions services/gam/src/contexts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ impl ContextManager {
token: [u32; 4],
clear: bool,
) -> Result<(), xous::Error> {
//log::set_max_level(log::LevelFilter::Trace);
self.notify_app_switch(token).ok();

let mut leaving_visibility: bool = false;
Expand Down Expand Up @@ -483,6 +484,7 @@ impl ContextManager {
self.redraw().expect("couldn't redraw the currently focused app");
}
}
//log::set_max_level(log::LevelFilter::Info);
Ok(())
}
pub(crate) fn set_pred_api_token(&mut self, at: ApiToken) {
Expand Down
2 changes: 1 addition & 1 deletion services/gam/src/layouts/modal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use graphics_server::*;
use crate::{LayoutApi, LayoutBehavior};

use crate::contexts::MISC_CONTEXT_DEFAULT_TRUST;
const TRUST_OFFSET: u8 = 1;
const TRUST_OFFSET: u8 = 16;

#[derive(Debug, Copy, Clone)]
pub(crate) struct ModalLayout {
Expand Down
3 changes: 3 additions & 0 deletions services/graphics-server/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ pub(crate) enum Opcode {
/// SuspendResume callback
SuspendResume,

/// draw the boot logo (for continuity as apps initialize)
DrawBootLogo,

Quit,
}

Expand Down
3 changes: 2 additions & 1 deletion services/graphics-server/src/backend/betrusted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ impl XousDisplay {
display
.susres
.push(RegOrField::Field(utra::memlcd::PRESCALER_PRESCALER), None);
display.sync_clear();

/*
use log::{error, info};
Expand Down Expand Up @@ -255,6 +254,7 @@ impl XousDisplay {

/// "synchronous clear" -- must be called on init, so that the state of the LCD
/// internal memory is consistent with the state of the frame buffer
/*
fn sync_clear(&mut self) {
let framebuffer = self.fb.as_mut_ptr() as *mut u32;
for words in 0..FB_SIZE {
Expand All @@ -267,6 +267,7 @@ impl XousDisplay {
self.update_all(); // because we force an all update here
while self.busy() {}
}
*/

fn busy(&self) -> bool {
self.csr.rf(utra::memlcd::BUSY_BUSY) == 1
Expand Down
8 changes: 8 additions & 0 deletions services/graphics-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,14 @@ impl Gfx {
.map(|_| ())
}

pub fn draw_boot_logo(&self) -> Result<(), xous::Error> {
send_message(
self.conn,
Message::new_scalar(Opcode::DrawBootLogo.to_usize().unwrap(), 0, 0, 0, 0),
)
.map(|_| ())
}

pub fn screen_size(&self) -> Result<Point, xous::Error> {
let response = send_message(
self.conn,
Expand Down
8 changes: 6 additions & 2 deletions services/graphics-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ fn wrapped_main() -> ! {
log::info!("my PID is {}", xous::process::id());

let mut display = XousDisplay::new();
draw_boot_logo(&mut display); // bring this up as soon as possible
let fontregion = map_fonts();

// install the graphical panic handler. It won't catch really early panics, or panics in this crate,
Expand Down Expand Up @@ -139,8 +140,6 @@ fn wrapped_main() -> ! {
.register_name(api::SERVER_NAME_GFX, Some(1))
.expect("can't register server");

draw_boot_logo(&mut display);

let screen_clip = Rectangle::new(Point::new(0, 0), display.screen_size());

display.redraw();
Expand Down Expand Up @@ -459,6 +458,11 @@ fn wrapped_main() -> ! {
display.update();
display.redraw();
}),
Some(Opcode::DrawBootLogo) => msg_scalar_unpack!(msg, _, _, _, _, {
display.blit_screen(&poweron::LOGO_MAP);
display.update();
display.redraw();
}),
Some(Opcode::Devboot) => msg_scalar_unpack!(msg, ena, _, _, _, {
if ena != 0 {
display.set_devboot(true);
Expand Down
7 changes: 7 additions & 0 deletions services/pddb/locales/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
"ja": "パスワードを認証失敗でした。\n\nもう一度実行しください。",
"zh": "密码错误。"
},
"pddb.waitmount": {
"en": "Mounting PDDB, please wait...",
"en-tts": "Mounting PDDB, please wait...",
"fr": "Montage de PDDB, veuillez patienter...*MT*",
"ja": "PDDB をマウントしています。お待ちください...",
"zh": "正在挂载 PDDB,请稍候..."
},
"pddb.basisname": {
"en": "Basis Name:",
"en-tts": "Enter name of Basis",
Expand Down
7 changes: 6 additions & 1 deletion services/pddb/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1940,11 +1940,14 @@ fn ensure_password(modals: &modals::Modals, pddb_os: &mut PddbOs, _pw_cid: xous:
fn try_mount_or_format(modals: &modals::Modals, pddb_os: &mut PddbOs, basis_cache: &mut BasisCache, pw_state: PasswordState, time_resetter: xous::CID) -> bool {
log::info!("Attempting to mount the PDDB");
if pw_state == PasswordState::Correct {
modals.dynamic_notification(Some(t!("pddb.waitmount", xous::LANG)), None).unwrap();
if let Some(sys_basis) = pddb_os.pddb_mount() {
log::info!("PDDB mount operation finished successfully");
basis_cache.basis_add(sys_basis);
modals.dynamic_notification_close().unwrap();
return true
}
modals.dynamic_notification_close().unwrap();
}
// correct password but no mount -> offer to format; uninit -> offer to format
if pw_state == PasswordState::Correct || pw_state == PasswordState::Uninit {
Expand Down Expand Up @@ -2001,12 +2004,14 @@ fn try_mount_or_format(modals: &modals::Modals, pddb_os: &mut PddbOs, basis_cach
0, 0, 0, 0
)
).expect("couldn't reset time");

modals.dynamic_notification(Some(t!("pddb.waitmount", xous::LANG)), None).unwrap();
if let Some(sys_basis) = pddb_os.pddb_mount() {
log::info!("PDDB mount operation finished successfully");
basis_cache.basis_add(sys_basis);
modals.dynamic_notification_close().unwrap();
true
} else {
modals.dynamic_notification_close().unwrap();
log::error!("Despite formatting, no PDDB was found!");
let mut err = String::from(t!("pddb.internalerror", xous::LANG));
err.push_str(" #1"); // punt and leave an error code, because this "should" be rare
Expand Down
7 changes: 7 additions & 0 deletions services/shellchat/locales/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,12 @@
"fr": "",
"ja": "",
"zh": ""
},
"shellchat.bootwait": {
"en": "Please wait...",
"en-tts": "Please wait...",
"fr": "S'il vous plaît, attendez*MT*",
"ja": "お待ちください...",
"zh": "请稍等..."
}
}
86 changes: 79 additions & 7 deletions services/shellchat/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,18 @@ Check for more detailed docs under Modules/cmds "Shell Chat" below
use log::info;

use core::fmt::Write;
use core::sync::atomic::{AtomicBool, Ordering};

use gam::UxRegistration;
use graphics_server::{Gid, Point, Rectangle, TextBounds, TextView, DrawStyle, PixelColor};
use graphics_server::api::GlyphStyle;
use xous::MessageEnvelope;
use xous_ipc::Buffer;

use locales::t;
use std::thread;
use std::sync::Arc;

#[doc = include_str!("../README.md")]
mod cmds;
use cmds::*;
Expand Down Expand Up @@ -202,7 +207,7 @@ impl Repl{
}

/// update the loop, in response to various inputs
fn update(&mut self, was_callback: bool) -> Result<(), xous::Error> {
fn update(&mut self, was_callback: bool, init_done: bool) -> Result<(), xous::Error> {
let debug1 = false;
// if we had an input string, do something
if let Some(local) = &self.input {
Expand All @@ -219,7 +224,7 @@ impl Repl{

// redraw UI once upon accepting all input
if !was_callback { // don't need to redraw on a callback, save some cycles
self.redraw().expect("can't redraw");
self.redraw(init_done).expect("can't redraw");
}

let mut dirty = true;
Expand Down Expand Up @@ -265,7 +270,7 @@ impl Repl{
self.msg = None;
// redraw UI now that we've responded
if dirty {
self.redraw().expect("can't redraw");
self.redraw(init_done).expect("can't redraw");
}

if debug1 {
Expand All @@ -286,10 +291,28 @@ impl Repl{
}
)).expect("can't clear content area");
}
fn redraw(&mut self) -> Result<(), xous::Error> {
fn redraw(&mut self, init_done: bool) -> Result<(), xous::Error> {
log::trace!("going into redraw");
self.clear_area();

if !init_done {
let mut init_tv = TextView::new(
self.content,
TextBounds::CenteredTop(
Rectangle::new(
Point::new(0, self.screensize.y / 3 - 64),
Point::new(self.screensize.x, self.screensize.y / 3)
)
)
);
init_tv.style = GlyphStyle::Bold;
init_tv.draw_border = false;
write!(init_tv.text, "{}", t!("shellchat.bootwait", xous::LANG)).ok();
self.gam.post_textview(&mut init_tv).expect("couldn't render wait text");
self.gam.redraw().expect("couldn't redraw screen");
return Ok(())
}

// this defines the bottom border of the text bubbles as they stack up wards
let mut bubble_baseline = self.screensize.y - self.margin.y;

Expand Down Expand Up @@ -393,8 +416,57 @@ fn wrapped_main() -> ! {
let mut was_callback = false;

let mut allow_redraw = true;
log::trace!("starting main loop");
let pddb_init_done = Arc::new(AtomicBool::new(false));

// spawn a thread to auto-mount the PDDB. It's important that this spawn happens after
// our GAM context has been registered (which happened in the `Repl::new()` call above)
repl.redraw(false).ok();
let _ = thread::spawn({
let pddb_init_done = pddb_init_done.clone();
let main_conn = xous::connect(shch_sid).unwrap();
move || {
let tt = ticktimer_server::Ticktimer::new().unwrap();
let xns = xous_names::XousNames::new().unwrap();
let gam = gam::Gam::new(&xns).unwrap();
while !gam.trusted_init_done().unwrap() {
tt.sleep_ms(50).ok();
}
loop {
let (no_retry_failure, count) = pddb::Pddb::new().try_mount();
pddb_init_done.store(true, Ordering::SeqCst);
if no_retry_failure {
// this includes both successfully mounted, and user abort of mount attempt
break;
} else {
// this indicates system was guttered due to a retry failure
let xns = xous_names::XousNames::new().unwrap();
let susres = susres::Susres::new_without_hook(&xns).unwrap();
let llio = llio::Llio::new(&xns);
if ((llio.adc_vbus().unwrap() as u32) * 503) < 150_000 {
// try to force suspend if possible, so that users who are just playing around with
// the device don't run the battery down accidentally.
susres.initiate_suspend().ok();
tt.sleep_ms(1000).unwrap();
let modals = modals::Modals::new(&xns).unwrap();
modals.show_notification(
&t!("login.fail", xous::LANG).replace("{fails}", &count.to_string()),
None
).ok();
} else {
// otherwise force a reboot cycle to slow down guessers
susres.reboot(true).expect("Couldn't reboot after too many failed password attempts");
tt.sleep_ms(5000).unwrap();
}
}
}
tt.sleep_ms(100).ok(); // this allows the shellchat context to foreground before calling the redraw
xous::send_message(main_conn,
xous::Message::new_scalar(ShellOpcode::Redraw.to_usize().unwrap(), 0, 0, 0, 0)
).ok();
}
});

log::trace!("starting main loop");
#[cfg(feature = "autobasis-ci")]
{
log::info!("starting autobasis CI launcher");
Expand All @@ -420,7 +492,7 @@ fn wrapped_main() -> ! {
}
Some(ShellOpcode::Redraw) => {
if allow_redraw {
repl.redraw().expect("REPL couldn't redraw");
repl.redraw(pddb_init_done.load(Ordering::SeqCst)).expect("REPL couldn't redraw");
}
}
Some(ShellOpcode::ChangeFocus) => xous::msg_scalar_unpack!(msg, new_state_code, _, _, _, {
Expand All @@ -446,7 +518,7 @@ fn wrapped_main() -> ! {
}
}
if update_repl {
repl.update(was_callback).expect("REPL had problems updating");
repl.update(was_callback, pddb_init_done.load(Ordering::SeqCst)).expect("REPL had problems updating");
update_repl = false;
}
log::trace!("reached bottom of main loop");
Expand Down
35 changes: 0 additions & 35 deletions services/status/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,41 +633,6 @@ fn wrapped_main() -> ! {
#[cfg(any(feature="precursor", feature="renode"))]
llio.clear_wakeup_alarm().unwrap(); // this is here to clear any wake-up alarms that were set by a prior coldboot command

// spawn a thread to auto-mount the PDDB
let _ = thread::spawn({
move || {
let tt = ticktimer_server::Ticktimer::new().unwrap();
tt.sleep_ms(2000).unwrap(); // a brief pause, to allow the other startup bits to finish running
loop {
let (no_retry_failure, count) = pddb::Pddb::new().try_mount();
if no_retry_failure {
// this includes both successfully mounted, and user abort of mount attempt
break;
} else {
// this indicates system was guttered due to a retry failure
let xns = xous_names::XousNames::new().unwrap();
let susres = susres::Susres::new_without_hook(&xns).unwrap();
let llio = llio::Llio::new(&xns);
if ((llio.adc_vbus().unwrap() as u32) * 503) < 150_000 {
// try to force suspend if possible, so that users who are just playing around with
// the device don't run the battery down accidentally.
susres.initiate_suspend().ok();
tt.sleep_ms(1000).unwrap();
let modals = modals::Modals::new(&xns).unwrap();
modals.show_notification(
&t!("login.fail", xous::LANG).replace("{fails}", &count.to_string()),
None
).ok();
} else {
// otherwise force a reboot cycle to slow down guessers
susres.reboot(true).expect("Couldn't reboot after too many failed password attempts");
tt.sleep_ms(5000).unwrap();
}
}
}
}
});

pump_run.store(true, Ordering::Relaxed); // start status thread updating
loop {
let msg = xous::receive_message(status_sid).unwrap();
Expand Down

0 comments on commit fa90e74

Please sign in to comment.