uefi: process: Add support to capture stdout · model-checking/verify-rust-std@b712e74 (original) (raw)

`@@ -91,9 +91,11 @@ impl Command {

`

91

91

`}

`

92

92

``

93

93

`pub fn output(&mut self) -> io::Result<(ExitStatus, Vec, Vec)> {

`

94

``

`-

let cmd = uefi_command_internal::Command::load_image(&self.prog)?;

`

``

94

`+

let mut cmd = uefi_command_internal::Command::load_image(&self.prog)?;

`

``

95

`+

cmd.stdout_init()?;

`

95

96

`let stat = cmd.start_image()?;

`

96

``

`-

Ok((ExitStatus(stat), Vec::new(), Vec::new()))

`

``

97

`+

let stdout = cmd.stdout()?;

`

``

98

`+

Ok((ExitStatus(stat), stdout, Vec::new()))

`

97

99

`}

`

98

100

`}

`

99

101

``

`@@ -246,20 +248,30 @@ impl<'a> fmt::Debug for CommandArgs<'a> {

`

246

248

`}

`

247

249

``

248

250

`mod uefi_command_internal {

`

``

251

`+

use r_efi::protocols::{loaded_image, simple_text_output};

`

``

252

+

249

253

`use super::super::helpers;

`

250

``

`-

use crate::ffi::OsStr;

`

``

254

`+

use crate::ffi::{OsStr, OsString};

`

251

255

`use crate::io::{self, const_io_error};

`

252

256

`use crate::mem::MaybeUninit;

`

253

257

`use crate::os::uefi::env::{boot_services, image_handle};

`

``

258

`+

use crate::os::uefi::ffi::OsStringExt;

`

254

259

`use crate::ptr::NonNull;

`

``

260

`+

use crate::slice;

`

``

261

`+

use crate::sys_common::wstr::WStrUnits;

`

255

262

``

256

263

`pub struct Command {

`

257

264

`handle: NonNullcrate::ffi::c_void,

`

``

265

`+

stdout: Option<helpers::Protocol>,

`

``

266

`+

st: Box<r_efi::efi::SystemTable>,

`

258

267

`}

`

259

268

``

260

269

`impl Command {

`

261

``

`-

const fn new(handle: NonNullcrate::ffi::c_void) -> Self {

`

262

``

`-

Self { handle }

`

``

270

`+

const fn new(

`

``

271

`+

handle: NonNullcrate::ffi::c_void,

`

``

272

`+

st: Box<r_efi::efi::SystemTable>,

`

``

273

`+

) -> Self {

`

``

274

`+

Self { handle, stdout: None, st }

`

263

275

`}

`

264

276

``

265

277

`pub fn load_image(p: &OsStr) -> io::Result {

`

`@@ -286,7 +298,17 @@ mod uefi_command_internal {

`

286

298

`} else {

`

287

299

`let child_handle = unsafe { child_handle.assume_init() };

`

288

300

`let child_handle = NonNull::new(child_handle).unwrap();

`

289

``

`-

Ok(Self::new(child_handle))

`

``

301

+

``

302

`+

let loaded_image: NonNull<loaded_image::Protocol> =

`

``

303

`+

helpers::open_protocol(child_handle, loaded_image::PROTOCOL_GUID).unwrap();

`

``

304

`+

let mut st: Box<r_efi::efi::SystemTable> =

`

``

305

`+

Box::new(unsafe { crate::ptr::read((*loaded_image.as_ptr()).system_table) });

`

``

306

+

``

307

`+

unsafe {

`

``

308

`+

(*loaded_image.as_ptr()).system_table = st.as_mut();

`

``

309

`+

}

`

``

310

+

``

311

`+

Ok(Self::new(child_handle, st))

`

290

312

`}

`

291

313

`}

`

292

314

``

`@@ -313,6 +335,32 @@ mod uefi_command_internal {

`

313

335

``

314

336

`Ok(r)

`

315

337

`}

`

``

338

+

``

339

`+

pub fn stdout_init(&mut self) -> io::Result<()> {

`

``

340

`+

let mut protocol =

`

``

341

`+

helpers::Protocol::create(PipeProtocol::new(), simple_text_output::PROTOCOL_GUID)?;

`

``

342

+

``

343

`+

self.st.console_out_handle = protocol.handle().as_ptr();

`

``

344

`+

self.st.con_out =

`

``

345

`+

protocol.as_mut() as *mut PipeProtocol as *mut simple_text_output::Protocol;

`

``

346

+

``

347

`+

self.stdout = Some(protocol);

`

``

348

+

``

349

`+

Ok(())

`

``

350

`+

}

`

``

351

+

``

352

`+

pub fn stdout(&self) -> io::Result<Vec> {

`

``

353

`+

if let Some(stdout) = &self.stdout {

`

``

354

`+

stdout

`

``

355

`+

.as_ref()

`

``

356

`+

.utf8()

`

``

357

`+

.into_string()

`

``

358

`+

.map_err(|_| const_io_error!(io::ErrorKind::Other, "utf8 conversion failed"))

`

``

359

`+

.map(Into::into)

`

``

360

`+

} else {

`

``

361

`+

Err(const_io_error!(io::ErrorKind::NotFound, "stdout not found"))

`

``

362

`+

}

`

``

363

`+

}

`

316

364

`}

`

317

365

``

318

366

`impl Drop for Command {

`

`@@ -325,4 +373,134 @@ mod uefi_command_internal {

`

325

373

`}

`

326

374

`}

`

327

375

`}

`

``

376

+

``

377

`+

#[repr(C)]

`

``

378

`+

struct PipeProtocol {

`

``

379

`+

reset: simple_text_output::ProtocolReset,

`

``

380

`+

output_string: simple_text_output::ProtocolOutputString,

`

``

381

`+

test_string: simple_text_output::ProtocolTestString,

`

``

382

`+

query_mode: simple_text_output::ProtocolQueryMode,

`

``

383

`+

set_mode: simple_text_output::ProtocolSetMode,

`

``

384

`+

set_attribute: simple_text_output::ProtocolSetAttribute,

`

``

385

`+

clear_screen: simple_text_output::ProtocolClearScreen,

`

``

386

`+

set_cursor_position: simple_text_output::ProtocolSetCursorPosition,

`

``

387

`+

enable_cursor: simple_text_output::ProtocolEnableCursor,

`

``

388

`+

mode: *mut simple_text_output::Mode,

`

``

389

`+

_mode: Box<simple_text_output::Mode>,

`

``

390

`+

_buffer: Vec,

`

``

391

`+

}

`

``

392

+

``

393

`+

impl PipeProtocol {

`

``

394

`+

fn new() -> Self {

`

``

395

`+

let mut mode = Box::new(simple_text_output::Mode {

`

``

396

`+

max_mode: 0,

`

``

397

`+

mode: 0,

`

``

398

`+

attribute: 0,

`

``

399

`+

cursor_column: 0,

`

``

400

`+

cursor_row: 0,

`

``

401

`+

cursor_visible: r_efi::efi::Boolean::FALSE,

`

``

402

`+

});

`

``

403

`+

Self {

`

``

404

`+

reset: Self::reset,

`

``

405

`+

output_string: Self::output_string,

`

``

406

`+

test_string: Self::test_string,

`

``

407

`+

query_mode: Self::query_mode,

`

``

408

`+

set_mode: Self::set_mode,

`

``

409

`+

set_attribute: Self::set_attribute,

`

``

410

`+

clear_screen: Self::clear_screen,

`

``

411

`+

set_cursor_position: Self::set_cursor_position,

`

``

412

`+

enable_cursor: Self::enable_cursor,

`

``

413

`+

mode: mode.as_mut(),

`

``

414

`+

_mode: mode,

`

``

415

`+

_buffer: Vec::new(),

`

``

416

`+

}

`

``

417

`+

}

`

``

418

+

``

419

`+

fn utf8(&self) -> OsString {

`

``

420

`+

OsString::from_wide(&self._buffer)

`

``

421

`+

}

`

``

422

+

``

423

`+

extern "efiapi" fn reset(

`

``

424

`+

proto: *mut simple_text_output::Protocol,

`

``

425

`+

_: r_efi::efi::Boolean,

`

``

426

`+

) -> r_efi::efi::Status {

`

``

427

`+

let proto: *mut PipeProtocol = proto.cast();

`

``

428

`+

unsafe {

`

``

429

`+

(*proto)._buffer.clear();

`

``

430

`+

}

`

``

431

`+

r_efi::efi::Status::SUCCESS

`

``

432

`+

}

`

``

433

+

``

434

`+

extern "efiapi" fn output_string(

`

``

435

`+

proto: *mut simple_text_output::Protocol,

`

``

436

`+

buf: *mut r_efi::efi::Char16,

`

``

437

`+

) -> r_efi::efi::Status {

`

``

438

`+

let proto: *mut PipeProtocol = proto.cast();

`

``

439

`+

let buf_len = unsafe {

`

``

440

`+

if let Some(x) = WStrUnits::new(buf) {

`

``

441

`+

x.count()

`

``

442

`+

} else {

`

``

443

`+

return r_efi::efi::Status::INVALID_PARAMETER;

`

``

444

`+

}

`

``

445

`+

};

`

``

446

`+

let buf_slice = unsafe { slice::from_raw_parts(buf, buf_len) };

`

``

447

+

``

448

`+

unsafe {

`

``

449

`+

(*proto)._buffer.extend_from_slice(buf_slice);

`

``

450

`+

};

`

``

451

+

``

452

`+

r_efi::efi::Status::SUCCESS

`

``

453

`+

}

`

``

454

+

``

455

`+

extern "efiapi" fn test_string(

`

``

456

`+

_: *mut simple_text_output::Protocol,

`

``

457

`+

_: *mut r_efi::efi::Char16,

`

``

458

`+

) -> r_efi::efi::Status {

`

``

459

`+

r_efi::efi::Status::SUCCESS

`

``

460

`+

}

`

``

461

+

``

462

`+

extern "efiapi" fn query_mode(

`

``

463

`+

_: *mut simple_text_output::Protocol,

`

``

464

`+

_: usize,

`

``

465

`+

_: *mut usize,

`

``

466

`+

_: *mut usize,

`

``

467

`+

) -> r_efi::efi::Status {

`

``

468

`+

r_efi::efi::Status::UNSUPPORTED

`

``

469

`+

}

`

``

470

+

``

471

`+

extern "efiapi" fn set_mode(

`

``

472

`+

_: *mut simple_text_output::Protocol,

`

``

473

`+

_: usize,

`

``

474

`+

) -> r_efi::efi::Status {

`

``

475

`+

r_efi::efi::Status::UNSUPPORTED

`

``

476

`+

}

`

``

477

+

``

478

`+

extern "efiapi" fn set_attribute(

`

``

479

`+

_: *mut simple_text_output::Protocol,

`

``

480

`+

_: usize,

`

``

481

`+

) -> r_efi::efi::Status {

`

``

482

`+

r_efi::efi::Status::UNSUPPORTED

`

``

483

`+

}

`

``

484

+

``

485

`+

extern "efiapi" fn clear_screen(

`

``

486

`+

_: *mut simple_text_output::Protocol,

`

``

487

`+

) -> r_efi::efi::Status {

`

``

488

`+

r_efi::efi::Status::UNSUPPORTED

`

``

489

`+

}

`

``

490

+

``

491

`+

extern "efiapi" fn set_cursor_position(

`

``

492

`+

_: *mut simple_text_output::Protocol,

`

``

493

`+

_: usize,

`

``

494

`+

_: usize,

`

``

495

`+

) -> r_efi::efi::Status {

`

``

496

`+

r_efi::efi::Status::UNSUPPORTED

`

``

497

`+

}

`

``

498

+

``

499

`+

extern "efiapi" fn enable_cursor(

`

``

500

`+

_: *mut simple_text_output::Protocol,

`

``

501

`+

_: r_efi::efi::Boolean,

`

``

502

`+

) -> r_efi::efi::Status {

`

``

503

`+

r_efi::efi::Status::UNSUPPORTED

`

``

504

`+

}

`

``

505

`+

}

`

328

506

`}

`