Rollup merge of #127462 - Ayush1325:uefi-env, r=joboet · qinheping/verify-rust-std@642ab07 (original) (raw)

`@@ -125,7 +125,7 @@ pub fn error_string(errno: RawOsError) -> String {

`

125

125

`}

`

126

126

``

127

127

`pub fn getcwd() -> io::Result {

`

128

``

`-

match uefi_shell::open_shell() {

`

``

128

`+

match helpers::open_shell() {

`

129

129

`Some(shell) => {

`

130

130

`// SAFETY: path_ptr is managed by UEFI shell and should not be deallocated

`

131

131

`let path_ptr = unsafe { ((*shell.as_ptr()).get_cur_dir)(crate::ptr::null_mut()) };

`

`@@ -144,7 +144,7 @@ pub fn getcwd() -> io::Result {

`

144

144

`}

`

145

145

``

146

146

`pub fn chdir(p: &path::Path) -> io::Result<()> {

`

147

``

`-

let shell = uefi_shell::open_shell().ok_or(unsupported_err())?;

`

``

147

`+

let shell = helpers::open_shell().ok_or(unsupported_err())?;

`

148

148

``

149

149

`let mut p = helpers::os_string_to_raw(p.as_os_str())

`

150

150

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

`

`@@ -192,44 +192,58 @@ pub fn current_exe() -> io::Result {

`

192

192

` helpers::device_path_to_text(protocol).map(PathBuf::from)

`

193

193

`}

`

194

194

``

195

``

`-

pub struct Env(!);

`

``

195

`+

pub struct EnvStrDebug<'a> {

`

``

196

`+

iter: &'a [(OsString, OsString)],

`

``

197

`+

}

`

``

198

+

``

199

`+

impl fmt::Debug for EnvStrDebug<'_> {

`

``

200

`+

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

`

``

201

`+

let mut list = f.debug_list();

`

``

202

`+

for (a, b) in self.iter {

`

``

203

`+

list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));

`

``

204

`+

}

`

``

205

`+

list.finish()

`

``

206

`+

}

`

``

207

`+

}

`

``

208

+

``

209

`+

pub struct Env(crate::vec::IntoIter<(OsString, OsString)>);

`

196

210

``

197

211

`impl Env {

`

198

212

`// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt.

`

199

213

`pub fn str_debug(&self) -> impl fmt::Debug + '_ {

`

200

``

`-

let Self(inner) = self;

`

201

``

`-

match *inner {}

`

``

214

`+

EnvStrDebug { iter: self.0.as_slice() }

`

202

215

`}

`

203

216

`}

`

204

217

``

205

218

`impl Iterator for Env {

`

206

219

`type Item = (OsString, OsString);

`

``

220

+

207

221

`fn next(&mut self) -> Option<(OsString, OsString)> {

`

208

``

`-

self.0

`

``

222

`+

self.0.next()

`

209

223

`}

`

210

224

`}

`

211

225

``

212

226

`impl fmt::Debug for Env {

`

213

``

`-

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

`

214

``

`-

let Self(inner) = self;

`

215

``

`-

match *inner {}

`

``

227

`+

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

`

``

228

`+

self.0.fmt(f)

`

216

229

`}

`

217

230

`}

`

218

231

``

219

232

`pub fn env() -> Env {

`

220

``

`-

panic!("not supported on this platform")

`

``

233

`+

let env = uefi_env::get_all().expect("not supported on this platform");

`

``

234

`+

Env(env.into_iter())

`

221

235

`}

`

222

236

``

223

``

`-

pub fn getenv(_: &OsStr) -> Option {

`

224

``

`-

None

`

``

237

`+

pub fn getenv(key: &OsStr) -> Option {

`

``

238

`+

uefi_env::get(key)

`

225

239

`}

`

226

240

``

227

``

`-

pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {

`

228

``

`-

Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))

`

``

241

`+

pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> {

`

``

242

`+

uefi_env::set(key, val)

`

229

243

`}

`

230

244

``

231

``

`-

pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {

`

232

``

`-

Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))

`

``

245

`+

pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> {

`

``

246

`+

uefi_env::unset(key)

`

233

247

`}

`

234

248

``

235

249

`pub fn temp_dir() -> PathBuf {

`

`@@ -261,36 +275,84 @@ pub fn getpid() -> u32 {

`

261

275

`panic!("no pids on this platform")

`

262

276

`}

`

263

277

``

264

``

`-

mod uefi_shell {

`

265

``

`-

use r_efi::protocols::shell;

`

266

``

-

267

``

`-

use super::super::helpers;

`

``

278

`+

mod uefi_env {

`

``

279

`+

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

`

``

280

`+

use crate::io;

`

``

281

`+

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

`

268

282

`use crate::ptr::NonNull;

`

269

``

`-

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

`

270

``

-

271

``

`-

pub fn open_shell() -> Option<NonNullshell::Protocol> {

`

272

``

`-

static LAST_VALID_HANDLE: AtomicPtrcrate::ffi::c_void =

`

273

``

`-

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

`

274

``

-

275

``

`-

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

`

276

``

`-

if let Ok(protocol) = helpers::open_protocol::shell::Protocol(

`

277

``

`-

handle,

`

278

``

`-

r_efi::protocols:🐚:PROTOCOL_GUID,

`

279

``

`-

) {

`

280

``

`-

return Some(protocol);

`

281

``

`-

}

`

``

283

`+

use crate::sys::{helpers, unsupported_err};

`

``

284

+

``

285

`+

pub(crate) fn get(key: &OsStr) -> Option {

`

``

286

`+

let shell = helpers::open_shell()?;

`

``

287

`+

let mut key_ptr = helpers::os_string_to_raw(key)?;

`

``

288

`+

unsafe { get_raw(shell, key_ptr.as_mut_ptr()) }

`

``

289

`+

}

`

``

290

+

``

291

`+

pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> {

`

``

292

`+

let mut key_ptr = helpers::os_string_to_raw(key)

`

``

293

`+

.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Key"))?;

`

``

294

`+

let mut val_ptr = helpers::os_string_to_raw(val)

`

``

295

`+

.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Value"))?;

`

``

296

`+

unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) }

`

``

297

`+

}

`

``

298

+

``

299

`+

pub(crate) fn unset(key: &OsStr) -> io::Result<()> {

`

``

300

`+

let mut key_ptr = helpers::os_string_to_raw(key)

`

``

301

`+

.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Key"))?;

`

``

302

`+

unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }

`

``

303

`+

}

`

``

304

+

``

305

`+

pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> {

`

``

306

`+

let shell = helpers::open_shell().ok_or(unsupported_err())?;

`

``

307

+

``

308

`+

let mut vars = Vec::new();

`

``

309

`+

let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) };

`

``

310

+

``

311

`+

if val.is_null() {

`

``

312

`+

return Ok(vars);

`

282

313

`}

`

283

314

``

284

``

`-

let handles = helpers::locate_handles(shell::PROTOCOL_GUID).ok()?;

`

285

``

`-

for handle in handles {

`

286

``

`-

if let Ok(protocol) =

`

287

``

`-

helpers::open_protocol::shell::Protocol(handle, shell::PROTOCOL_GUID)

`

288

``

`-

{

`

289

``

`-

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

`

290

``

`-

return Some(protocol);

`

``

315

`+

let mut start = 0;

`

``

316

+

``

317

`+

// UEFI Shell returns all keys seperated by NULL.

`

``

318

`+

// End of string is denoted by two NULLs

`

``

319

`+

for i in 0.. {

`

``

320

`+

if unsafe { *val.add(i) } == 0 {

`

``

321

`+

// Two NULL signal end of string

`

``

322

`+

if i == start {

`

``

323

`+

break;

`

``

324

`+

}

`

``

325

+

``

326

`+

let key = OsString::from_wide(unsafe {

`

``

327

`+

crate::slice::from_raw_parts(val.add(start), i - start)

`

``

328

`+

});

`

``

329

`+

// SAFETY: val.add(start) is always NULL terminated

`

``

330

`+

let val = unsafe { get_raw(shell, val.add(start)) }

`

``

331

`+

.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Value"))?;

`

``

332

+

``

333

`+

vars.push((key, val));

`

``

334

`+

start = i + 1;

`

291

335

`}

`

292

336

`}

`

293

337

``

294

``

`-

None

`

``

338

`+

Ok(vars)

`

``

339

`+

}

`

``

340

+

``

341

`+

unsafe fn get_raw(

`

``

342

`+

shell: NonNull<r_efi::efi::protocols:🐚:Protocol>,

`

``

343

`+

key_ptr: *mut r_efi::efi::Char16,

`

``

344

`+

) -> Option {

`

``

345

`+

let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) };

`

``

346

`+

helpers::os_string_from_raw(val)

`

``

347

`+

}

`

``

348

+

``

349

`+

unsafe fn set_raw(

`

``

350

`+

key_ptr: *mut r_efi::efi::Char16,

`

``

351

`+

val_ptr: *mut r_efi::efi::Char16,

`

``

352

`+

) -> io::Result<()> {

`

``

353

`+

let shell = helpers::open_shell().ok_or(unsupported_err())?;

`

``

354

`+

let r =

`

``

355

`+

unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) };

`

``

356

`+

if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }

`

295

357

`}

`

296

358

`}

`