Rollup merge of #123196 - Ayush1325:uefi-process, r=joboet · model-checking/verify-rust-std@a077eb1 (original) (raw)

`@@ -12,15 +12,21 @@

`

12

12

`use r_efi::efi::{self, Guid};

`

13

13

`use r_efi::protocols::{device_path, device_path_to_text};

`

14

14

``

15

``

`-

use crate::ffi::OsString;

`

``

15

`+

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

`

16

16

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

`

17

17

`use crate::mem::{size_of, MaybeUninit};

`

18

``

`-

use crate::os::uefi::{self, env::boot_services, ffi::OsStringExt};

`

``

18

`+

use crate::os::uefi::{self, env::boot_services, ffi::OsStrExt, ffi::OsStringExt};

`

19

19

`use crate::ptr::NonNull;

`

20

20

`use crate::slice;

`

21

21

`use crate::sync::atomic::{AtomicPtr, Ordering};

`

22

22

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

`

23

23

``

``

24

`+

type BootInstallMultipleProtocolInterfaces =

`

``

25

`+

unsafe extern "efiapi" fn(_: *mut r_efi::efi::Handle, _: ...) -> r_efi::efi::Status;

`

``

26

+

``

27

`+

type BootUninstallMultipleProtocolInterfaces =

`

``

28

`+

unsafe extern "efiapi" fn(_: r_efi::efi::Handle, _: ...) -> r_efi::efi::Status;

`

``

29

+

24

30

`const BOOT_SERVICES_UNAVAILABLE: io::Error =

`

25

31

`const_io_error!(io::ErrorKind::Other, "Boot Services are no longer available");

`

26

32

``

`@@ -221,3 +227,192 @@ pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>>

`

221

227

`let runtime_services = unsafe { (*system_table.as_ptr()).runtime_services };

`

222

228

`NonNull::new(runtime_services)

`

223

229

`}

`

``

230

+

``

231

`+

pub(crate) struct DevicePath(NonNull<r_efi::protocols::device_path::Protocol>);

`

``

232

+

``

233

`+

impl DevicePath {

`

``

234

`+

pub(crate) fn from_text(p: &OsStr) -> io::Result {

`

``

235

`+

fn inner(

`

``

236

`+

p: &OsStr,

`

``

237

`+

protocol: NonNull<r_efi::protocols::device_path_from_text::Protocol>,

`

``

238

`+

) -> io::Result {

`

``

239

`+

let path_vec = p.encode_wide().chain(Some(0)).collect::<Vec>();

`

``

240

`+

if path_vec[..path_vec.len() - 1].contains(&0) {

`

``

241

`+

return Err(const_io_error!(

`

``

242

`+

io::ErrorKind::InvalidInput,

`

``

243

`+

"strings passed to UEFI cannot contain NULs",

`

``

244

`+

));

`

``

245

`+

}

`

``

246

+

``

247

`+

let path =

`

``

248

`+

unsafe { ((*protocol.as_ptr()).convert_text_to_device_path)(path_vec.as_ptr()) };

`

``

249

+

``

250

`+

NonNull::new(path).map(DevicePath).ok_or_else(|| {

`

``

251

`+

const_io_error!(io::ErrorKind::InvalidFilename, "Invalid Device Path")

`

``

252

`+

})

`

``

253

`+

}

`

``

254

+

``

255

`+

static LAST_VALID_HANDLE: AtomicPtrcrate::ffi::c_void =

`

``

256

`+

AtomicPtr::new(crate::ptr::null_mut());

`

``

257

+

``

258

`+

if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {

`

``

259

`+

if let Ok(protocol) = open_protocol::<r_efi::protocols::device_path_from_text::Protocol>(

`

``

260

`+

handle,

`

``

261

`+

r_efi::protocols::device_path_from_text::PROTOCOL_GUID,

`

``

262

`+

) {

`

``

263

`+

return inner(p, protocol);

`

``

264

`+

}

`

``

265

`+

}

`

``

266

+

``

267

`+

let handles = locate_handles(r_efi::protocols::device_path_from_text::PROTOCOL_GUID)?;

`

``

268

`+

for handle in handles {

`

``

269

`+

if let Ok(protocol) = open_protocol::<r_efi::protocols::device_path_from_text::Protocol>(

`

``

270

`+

handle,

`

``

271

`+

r_efi::protocols::device_path_from_text::PROTOCOL_GUID,

`

``

272

`+

) {

`

``

273

`+

LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);

`

``

274

`+

return inner(p, protocol);

`

``

275

`+

}

`

``

276

`+

}

`

``

277

+

``

278

`+

io::Result::Err(const_io_error!(

`

``

279

`+

io::ErrorKind::NotFound,

`

``

280

`+

"DevicePathFromText Protocol not found"

`

``

281

`+

))

`

``

282

`+

}

`

``

283

+

``

284

`+

pub(crate) fn as_ptr(&self) -> *mut r_efi::protocols::device_path::Protocol {

`

``

285

`+

self.0.as_ptr()

`

``

286

`+

}

`

``

287

`+

}

`

``

288

+

``

289

`+

impl Drop for DevicePath {

`

``

290

`+

fn drop(&mut self) {

`

``

291

`+

if let Some(bt) = boot_services() {

`

``

292

`+

let bt: NonNull<r_efi::efi::BootServices> = bt.cast();

`

``

293

`+

unsafe {

`

``

294

`+

((*bt.as_ptr()).free_pool)(self.0.as_ptr() as *mut crate::ffi::c_void);

`

``

295

`+

}

`

``

296

`+

}

`

``

297

`+

}

`

``

298

`+

}

`

``

299

+

``

300

`+

pub(crate) struct OwnedProtocol {

`

``

301

`+

guid: r_efi::efi::Guid,

`

``

302

`+

handle: NonNullcrate::ffi::c_void,

`

``

303

`+

protocol: *mut T,

`

``

304

`+

}

`

``

305

+

``

306

`+

impl OwnedProtocol {

`

``

307

`+

// FIXME: Consider using unsafe trait for matching protocol with guid

`

``

308

`+

pub(crate) unsafe fn create(protocol: T, mut guid: r_efi::efi::Guid) -> io::Result {

`

``

309

`+

let bt: NonNull<r_efi::efi::BootServices> =

`

``

310

`+

boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();

`

``

311

`+

let protocol: *mut T = Box::into_raw(Box::new(protocol));

`

``

312

`+

let mut handle: r_efi::efi::Handle = crate::ptr::null_mut();

`

``

313

+

``

314

`+

// FIXME: Move into r-efi once extended_varargs_abi_support is stablized

`

``

315

`+

let func: BootInstallMultipleProtocolInterfaces =

`

``

316

`+

unsafe { crate::mem::transmute((*bt.as_ptr()).install_multiple_protocol_interfaces) };

`

``

317

+

``

318

`+

let r = unsafe {

`

``

319

`+

func(

`

``

320

`+

&mut handle,

`

``

321

`+

&mut guid as *mut _ as *mut crate::ffi::c_void,

`

``

322

`+

protocol as *mut crate::ffi::c_void,

`

``

323

`+

crate::ptr::null_mut() as *mut crate::ffi::c_void,

`

``

324

`+

)

`

``

325

`+

};

`

``

326

+

``

327

`+

if r.is_error() {

`

``

328

`+

drop(unsafe { Box::from_raw(protocol) });

`

``

329

`+

return Err(crate::io::Error::from_raw_os_error(r.as_usize()));

`

``

330

`+

};

`

``

331

+

``

332

`+

let handle = NonNull::new(handle)

`

``

333

`+

.ok_or(io::const_io_error!(io::ErrorKind::Uncategorized, "found null handle"))?;

`

``

334

+

``

335

`+

Ok(Self { guid, handle, protocol })

`

``

336

`+

}

`

``

337

+

``

338

`+

pub(crate) fn handle(&self) -> NonNullcrate::ffi::c_void {

`

``

339

`+

self.handle

`

``

340

`+

}

`

``

341

`+

}

`

``

342

+

``

343

`+

impl Drop for OwnedProtocol {

`

``

344

`+

fn drop(&mut self) {

`

``

345

`+

// Do not deallocate a runtime protocol

`

``

346

`+

if let Some(bt) = boot_services() {

`

``

347

`+

let bt: NonNull<r_efi::efi::BootServices> = bt.cast();

`

``

348

`+

// FIXME: Move into r-efi once extended_varargs_abi_support is stablized

`

``

349

`+

let func: BootUninstallMultipleProtocolInterfaces = unsafe {

`

``

350

`+

crate::mem::transmute((*bt.as_ptr()).uninstall_multiple_protocol_interfaces)

`

``

351

`+

};

`

``

352

`+

let status = unsafe {

`

``

353

`+

func(

`

``

354

`+

self.handle.as_ptr(),

`

``

355

`+

&mut self.guid as *mut _ as *mut crate::ffi::c_void,

`

``

356

`+

self.protocol as *mut crate::ffi::c_void,

`

``

357

`+

crate::ptr::null_mut() as *mut crate::ffi::c_void,

`

``

358

`+

)

`

``

359

`+

};

`

``

360

+

``

361

`+

// Leak the protocol in case uninstall fails

`

``

362

`+

if status == r_efi::efi::Status::SUCCESS {

`

``

363

`+

let _ = unsafe { Box::from_raw(self.protocol) };

`

``

364

`+

}

`

``

365

`+

}

`

``

366

`+

}

`

``

367

`+

}

`

``

368

+

``

369

`+

impl AsRef for OwnedProtocol {

`

``

370

`+

fn as_ref(&self) -> &T {

`

``

371

`+

unsafe { self.protocol.as_ref().unwrap() }

`

``

372

`+

}

`

``

373

`+

}

`

``

374

+

``

375

`+

pub(crate) struct OwnedTable {

`

``

376

`+

layout: crate::alloc::Layout,

`

``

377

`+

ptr: *mut T,

`

``

378

`+

}

`

``

379

+

``

380

`+

impl OwnedTable {

`

``

381

`+

pub(crate) fn from_table_header(hdr: &r_efi::efi::TableHeader) -> Self {

`

``

382

`+

let header_size = hdr.header_size as usize;

`

``

383

`+

let layout = crate::alloc::Layout::from_size_align(header_size, 8).unwrap();

`

``

384

`+

let ptr = unsafe { crate::alloc::alloc(layout) as *mut T };

`

``

385

`+

Self { layout, ptr }

`

``

386

`+

}

`

``

387

+

``

388

`+

pub(crate) const fn as_ptr(&self) -> *const T {

`

``

389

`+

self.ptr

`

``

390

`+

}

`

``

391

+

``

392

`+

pub(crate) const fn as_mut_ptr(&self) -> *mut T {

`

``

393

`+

self.ptr

`

``

394

`+

}

`

``

395

`+

}

`

``

396

+

``

397

`+

impl OwnedTable<r_efi::efi::SystemTable> {

`

``

398

`+

pub(crate) fn from_table(tbl: *const r_efi::efi::SystemTable) -> Self {

`

``

399

`+

let hdr = unsafe { (*tbl).hdr };

`

``

400

+

``

401

`+

let owned_tbl = Self::from_table_header(&hdr);

`

``

402

`+

unsafe {

`

``

403

`+

crate::ptr::copy_nonoverlapping(

`

``

404

`+

tbl as *const u8,

`

``

405

`+

owned_tbl.as_mut_ptr() as *mut u8,

`

``

406

`+

hdr.header_size as usize,

`

``

407

`+

)

`

``

408

`+

};

`

``

409

+

``

410

`+

owned_tbl

`

``

411

`+

}

`

``

412

`+

}

`

``

413

+

``

414

`+

impl Drop for OwnedTable {

`

``

415

`+

fn drop(&mut self) {

`

``

416

`+

unsafe { crate::alloc::dealloc(self.ptr as *mut u8, self.layout) };

`

``

417

`+

}

`

``

418

`+

}

`