Auto merge of #137424 - Ayush1325:uefi-path-node, r=nicholasbishop,cu… · rust-lang/rust@cb50d4d (original) (raw)

`@@ -216,6 +216,60 @@ pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::R

`

216

216

`Err(io::const_error!(io::ErrorKind::NotFound, "no device path to text protocol found"))

`

217

217

`}

`

218

218

``

``

219

`+

fn device_node_to_text(path: NonNull<device_path::Protocol>) -> io::Result {

`

``

220

`+

fn node_to_text(

`

``

221

`+

protocol: NonNull<device_path_to_text::Protocol>,

`

``

222

`+

path: NonNull<device_path::Protocol>,

`

``

223

`+

) -> io::Result {

`

``

224

`+

let path_ptr: *mut r_efi::efi::Char16 = unsafe {

`

``

225

`+

((*protocol.as_ptr()).convert_device_node_to_text)(

`

``

226

`+

path.as_ptr(),

`

``

227

`+

// DisplayOnly

`

``

228

`+

r_efi::efi::Boolean::FALSE,

`

``

229

`+

// AllowShortcuts

`

``

230

`+

r_efi::efi::Boolean::FALSE,

`

``

231

`+

)

`

``

232

`+

};

`

``

233

+

``

234

`+

let path = os_string_from_raw(path_ptr)

`

``

235

`+

.ok_or(io::const_error!(io::ErrorKind::InvalidData, "Invalid path"))?;

`

``

236

+

``

237

`+

if let Some(boot_services) = crate::os::uefi::env::boot_services() {

`

``

238

`+

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

`

``

239

`+

unsafe {

`

``

240

`+

((*boot_services.as_ptr()).free_pool)(path_ptr.cast());

`

``

241

`+

}

`

``

242

`+

}

`

``

243

+

``

244

`+

Ok(path)

`

``

245

`+

}

`

``

246

+

``

247

`+

static LAST_VALID_HANDLE: AtomicPtrcrate::ffi::c_void =

`

``

248

`+

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

`

``

249

+

``

250

`+

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

`

``

251

`+

if let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>(

`

``

252

`+

handle,

`

``

253

`+

device_path_to_text::PROTOCOL_GUID,

`

``

254

`+

) {

`

``

255

`+

return node_to_text(protocol, path);

`

``

256

`+

}

`

``

257

`+

}

`

``

258

+

``

259

`+

let device_path_to_text_handles = locate_handles(device_path_to_text::PROTOCOL_GUID)?;

`

``

260

`+

for handle in device_path_to_text_handles {

`

``

261

`+

if let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>(

`

``

262

`+

handle,

`

``

263

`+

device_path_to_text::PROTOCOL_GUID,

`

``

264

`+

) {

`

``

265

`+

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

`

``

266

`+

return node_to_text(protocol, path);

`

``

267

`+

}

`

``

268

`+

}

`

``

269

+

``

270

`+

Err(io::const_error!(io::ErrorKind::NotFound, "No device path to text protocol found"))

`

``

271

`+

}

`

``

272

+

219

273

`/// Gets RuntimeServices.

`

220

274

`pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>> {

`

221

275

`let system_table: NonNull<r_efi::efi::SystemTable> =

`

`@@ -319,6 +373,11 @@ impl<'a> BorrowedDevicePath<'a> {

`

319

373

`pub(crate) fn to_text(&self) -> io::Result {

`

320

374

`device_path_to_text(self.protocol)

`

321

375

`}

`

``

376

+

``

377

`+

#[expect(dead_code)]

`

``

378

`+

pub(crate) const fn iter(&'a self) -> DevicePathIterator<'a> {

`

``

379

`+

DevicePathIterator::new(DevicePathNode::new(self.protocol))

`

``

380

`+

}

`

322

381

`}

`

323

382

``

324

383

`impl<'a> crate::fmt::Debug for BorrowedDevicePath<'a> {

`

`@@ -330,6 +389,126 @@ impl<'a> crate::fmt::Debug for BorrowedDevicePath<'a> {

`

330

389

`}

`

331

390

`}

`

332

391

``

``

392

`+

pub(crate) struct DevicePathIterator<'a>(Option<DevicePathNode<'a>>);

`

``

393

+

``

394

`+

impl<'a> DevicePathIterator<'a> {

`

``

395

`+

const fn new(node: DevicePathNode<'a>) -> Self {

`

``

396

`+

if node.is_end() { Self(None) } else { Self(Some(node)) }

`

``

397

`+

}

`

``

398

`+

}

`

``

399

+

``

400

`+

impl<'a> Iterator for DevicePathIterator<'a> {

`

``

401

`+

type Item = DevicePathNode<'a>;

`

``

402

+

``

403

`+

fn next(&mut self) -> OptionSelf::Item {

`

``

404

`+

let cur_node = self.0?;

`

``

405

+

``

406

`+

let next_node = unsafe { cur_node.next_node() };

`

``

407

`+

self.0 = if next_node.is_end() { None } else { Some(next_node) };

`

``

408

+

``

409

`+

Some(cur_node)

`

``

410

`+

}

`

``

411

`+

}

`

``

412

+

``

413

`+

#[derive(Copy, Clone)]

`

``

414

`+

pub(crate) struct DevicePathNode<'a> {

`

``

415

`+

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

`

``

416

`+

phantom: PhantomData<&'a r_efi::protocols::device_path::Protocol>,

`

``

417

`+

}

`

``

418

+

``

419

`+

impl<'a> DevicePathNode<'a> {

`

``

420

`+

pub(crate) const fn new(protocol: NonNull<r_efi::protocols::device_path::Protocol>) -> Self {

`

``

421

`+

Self { protocol, phantom: PhantomData }

`

``

422

`+

}

`

``

423

+

``

424

`+

pub(crate) const fn length(&self) -> u16 {

`

``

425

`+

let len = unsafe { (*self.protocol.as_ptr()).length };

`

``

426

`+

u16::from_le_bytes(len)

`

``

427

`+

}

`

``

428

+

``

429

`+

pub(crate) const fn node_type(&self) -> u8 {

`

``

430

`+

unsafe { (*self.protocol.as_ptr()).r#type }

`

``

431

`+

}

`

``

432

+

``

433

`+

pub(crate) const fn sub_type(&self) -> u8 {

`

``

434

`+

unsafe { (*self.protocol.as_ptr()).sub_type }

`

``

435

`+

}

`

``

436

+

``

437

`+

pub(crate) fn data(&self) -> &[u8] {

`

``

438

`+

let length: usize = self.length().into();

`

``

439

+

``

440

`+

// Some nodes do not have any special data

`

``

441

`+

if length > 4 {

`

``

442

`+

let raw_ptr: *const u8 = self.protocol.as_ptr().cast();

`

``

443

`+

let data = unsafe { raw_ptr.add(4) };

`

``

444

`+

unsafe { crate::slice::from_raw_parts(data, length - 4) }

`

``

445

`+

} else {

`

``

446

`+

&[]

`

``

447

`+

}

`

``

448

`+

}

`

``

449

+

``

450

`+

pub(crate) const fn is_end(&self) -> bool {

`

``

451

`+

self.node_type() == r_efi::protocols::device_path::TYPE_END

`

``

452

`+

&& self.sub_type() == r_efi::protocols::device_path::End::SUBTYPE_ENTIRE

`

``

453

`+

}

`

``

454

+

``

455

`+

#[expect(dead_code)]

`

``

456

`+

pub(crate) const fn is_end_instance(&self) -> bool {

`

``

457

`+

self.node_type() == r_efi::protocols::device_path::TYPE_END

`

``

458

`+

&& self.sub_type() == r_efi::protocols::device_path::End::SUBTYPE_INSTANCE

`

``

459

`+

}

`

``

460

+

``

461

`+

pub(crate) unsafe fn next_node(&self) -> Self {

`

``

462

`+

let node = unsafe {

`

``

463

`+

self.protocol

`

``

464

`+

.cast::()

`

``

465

`+

.add(self.length().into())

`

``

466

`+

.cast::<r_efi::protocols::device_path::Protocol>()

`

``

467

`+

};

`

``

468

`+

Self::new(node)

`

``

469

`+

}

`

``

470

+

``

471

`+

#[expect(dead_code)]

`

``

472

`+

pub(crate) fn to_path(&'a self) -> BorrowedDevicePath<'a> {

`

``

473

`+

BorrowedDevicePath::new(self.protocol)

`

``

474

`+

}

`

``

475

+

``

476

`+

pub(crate) fn to_text(&self) -> io::Result {

`

``

477

`+

device_node_to_text(self.protocol)

`

``

478

`+

}

`

``

479

`+

}

`

``

480

+

``

481

`+

impl<'a> PartialEq for DevicePathNode<'a> {

`

``

482

`+

fn eq(&self, other: &Self) -> bool {

`

``

483

`+

let self_len = self.length();

`

``

484

`+

let other_len = other.length();

`

``

485

+

``

486

`+

self_len == other_len

`

``

487

`+

&& unsafe {

`

``

488

`+

compiler_builtins::mem::memcmp(

`

``

489

`+

self.protocol.as_ptr().cast(),

`

``

490

`+

other.protocol.as_ptr().cast(),

`

``

491

`+

usize::from(self_len),

`

``

492

`+

) == 0

`

``

493

`+

}

`

``

494

`+

}

`

``

495

`+

}

`

``

496

+

``

497

`+

impl<'a> crate::fmt::Debug for DevicePathNode<'a> {

`

``

498

`+

fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {

`

``

499

`+

match self.to_text() {

`

``

500

`+

Ok(p) => p.fmt(f),

`

``

501

`+

Err(_) => f

`

``

502

`+

.debug_struct("DevicePathNode")

`

``

503

`+

.field("type", &self.node_type())

`

``

504

`+

.field("sub_type", &self.sub_type())

`

``

505

`+

.field("length", &self.length())

`

``

506

`+

.field("specific_device_path_data", &self.data())

`

``

507

`+

.finish(),

`

``

508

`+

}

`

``

509

`+

}

`

``

510

`+

}

`

``

511

+

333

512

`pub(crate) struct OwnedProtocol {

`

334

513

`guid: r_efi::efi::Guid,

`

335

514

`handle: NonNullcrate::ffi::c_void,

`