1 /* $NetBSD: hand.c,v 1.5 2021/09/30 19:02:48 jmcneill Exp $ */
2
3 /*++
4
5 Copyright (c) 1998 Intel Corporation
6
7 Module Name:
8
9 hand.c
10
11 Abstract:
12
13
14
15
16 Revision History
17
18 --*/
19
20 #include "lib.h"
21 #include "efistdarg.h" // !!!
22
23
24 EFI_STATUS
LibLocateProtocol(IN EFI_GUID * ProtocolGuid,OUT VOID ** Interface)25 LibLocateProtocol (
26 IN EFI_GUID *ProtocolGuid,
27 OUT VOID **Interface
28 )
29 //
30 // Find the first instance of this Protocol in the system and return it's interface
31 //
32 {
33 EFI_STATUS Status;
34 UINTN NumberHandles, Index;
35 EFI_HANDLE *Handles;
36
37
38 *Interface = NULL;
39 Status = LibLocateHandle (ByProtocol, ProtocolGuid, NULL, &NumberHandles, &Handles);
40 if (EFI_ERROR(Status)) {
41 DEBUG((D_INFO, "LibLocateProtocol: Handle not found\n"));
42 return Status;
43 }
44
45 for (Index=0; Index < NumberHandles; Index++) {
46 Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handles[Index], ProtocolGuid, Interface);
47 if (!EFI_ERROR(Status)) {
48 break;
49 }
50 }
51
52 if (Handles) {
53 FreePool (Handles);
54 }
55
56 return Status;
57 }
58
59 EFI_STATUS
LibLocateHandle(IN EFI_LOCATE_SEARCH_TYPE SearchType,IN EFI_GUID * Protocol OPTIONAL,IN VOID * SearchKey OPTIONAL,IN OUT UINTN * NoHandles,OUT EFI_HANDLE ** Buffer)60 LibLocateHandle (
61 IN EFI_LOCATE_SEARCH_TYPE SearchType,
62 IN EFI_GUID *Protocol OPTIONAL,
63 IN VOID *SearchKey OPTIONAL,
64 IN OUT UINTN *NoHandles,
65 OUT EFI_HANDLE **Buffer
66 )
67
68 {
69 EFI_STATUS Status;
70 UINTN BufferSize;
71
72 //
73 // Initialize for GrowBuffer loop
74 //
75
76 Status = EFI_SUCCESS;
77 *Buffer = NULL;
78 BufferSize = 50 * sizeof(EFI_HANDLE);
79
80 //
81 // Call the real function
82 //
83
84 while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) {
85
86 Status = uefi_call_wrapper(
87 BS->LocateHandle,
88 5,
89 SearchType,
90 Protocol,
91 SearchKey,
92 &BufferSize,
93 *Buffer
94 );
95
96 }
97
98 *NoHandles = BufferSize / sizeof (EFI_HANDLE);
99 if (EFI_ERROR(Status)) {
100 *NoHandles = 0;
101 }
102
103 return Status;
104 }
105
106 EFI_STATUS
LibLocateHandleByDiskSignature(IN UINT8 MBRType,IN UINT8 SignatureType,IN VOID * Signature,IN OUT UINTN * NoHandles,OUT EFI_HANDLE ** Buffer)107 LibLocateHandleByDiskSignature (
108 IN UINT8 MBRType,
109 IN UINT8 SignatureType,
110 IN VOID *Signature,
111 IN OUT UINTN *NoHandles,
112 OUT EFI_HANDLE **Buffer
113 )
114
115 {
116 EFI_STATUS Status;
117 UINTN BufferSize;
118 UINTN NoBlockIoHandles;
119 EFI_HANDLE *BlockIoBuffer;
120 EFI_DEVICE_PATH *DevicePath;
121 UINTN Index;
122 EFI_DEVICE_PATH *Next, *DevPath;
123 HARDDRIVE_DEVICE_PATH *HardDriveDevicePath;
124 BOOLEAN Match;
125 BOOLEAN PreviousNodeIsHardDriveDevicePath;
126
127 //
128 // Initialize for GrowBuffer loop
129 //
130
131 Status = EFI_SUCCESS;
132 BlockIoBuffer = NULL;
133 BufferSize = 50 * sizeof(EFI_HANDLE);
134
135 //
136 // Call the real function
137 //
138
139 while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) {
140
141 //
142 // Get list of device handles that support the BLOCK_IO Protocol.
143 //
144
145 Status = uefi_call_wrapper(
146 BS->LocateHandle,
147 5,
148 ByProtocol,
149 &BlockIoProtocol,
150 NULL,
151 &BufferSize,
152 BlockIoBuffer
153 );
154
155 }
156
157 NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE);
158 if (EFI_ERROR(Status)) {
159 NoBlockIoHandles = 0;
160 }
161
162 //
163 // If there was an error or there are no device handles that support
164 // the BLOCK_IO Protocol, then return.
165 //
166
167 if (NoBlockIoHandles == 0) {
168 FreePool(BlockIoBuffer);
169 *NoHandles = 0;
170 *Buffer = NULL;
171 return Status;
172 }
173
174 //
175 // Loop through all the device handles that support the BLOCK_IO Protocol
176 //
177
178 *NoHandles = 0;
179
180 for(Index=0;Index<NoBlockIoHandles;Index++) {
181
182 Status = uefi_call_wrapper(
183 BS->HandleProtocol,
184 3,
185 BlockIoBuffer[Index],
186 &DevicePathProtocol,
187 (VOID*)&DevicePath
188 );
189
190 //
191 // Search DevicePath for a Hard Drive Media Device Path node.
192 // If one is found, then see if it matches the signature that was
193 // passed in. If it does match, and the next node is the End of the
194 // device path, and the previous node is not a Hard Drive Media Device
195 // Path, then we have found a match.
196 //
197
198 Match = FALSE;
199
200 if (DevicePath != NULL) {
201
202 PreviousNodeIsHardDriveDevicePath = FALSE;
203
204 DevPath = DevicePath;
205
206 //
207 // Check for end of device path type
208 //
209
210 for (; ;) {
211
212 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
213 (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
214
215 HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath);
216
217 if (PreviousNodeIsHardDriveDevicePath == FALSE) {
218
219 Next = NextDevicePathNode(DevPath);
220 if (IsDevicePathEndType(Next)) {
221 if ((HardDriveDevicePath->MBRType == MBRType) &&
222 (HardDriveDevicePath->SignatureType == SignatureType)) {
223 switch(SignatureType) {
224 case SIGNATURE_TYPE_MBR:
225 if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) {
226 Match = TRUE;
227 }
228 break;
229 case SIGNATURE_TYPE_GUID:
230 if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) {
231 Match = TRUE;
232 }
233 break;
234 }
235 }
236 }
237 }
238 PreviousNodeIsHardDriveDevicePath = TRUE;
239 } else {
240 PreviousNodeIsHardDriveDevicePath = FALSE;
241 }
242
243 if (IsDevicePathEnd(DevPath)) {
244 break;
245 }
246
247 DevPath = NextDevicePathNode(DevPath);
248 }
249
250 }
251
252 if (Match == FALSE) {
253 BlockIoBuffer[Index] = NULL;
254 } else {
255 *NoHandles = *NoHandles + 1;
256 }
257 }
258
259 //
260 // If there are no matches, then return
261 //
262
263 if (*NoHandles == 0) {
264 FreePool(BlockIoBuffer);
265 *NoHandles = 0;
266 *Buffer = NULL;
267 return EFI_SUCCESS;
268 }
269
270 //
271 // Allocate space for the return buffer of device handles.
272 //
273
274 *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE));
275
276 if (*Buffer == NULL) {
277 FreePool(BlockIoBuffer);
278 *NoHandles = 0;
279 *Buffer = NULL;
280 return EFI_OUT_OF_RESOURCES;
281 }
282
283 //
284 // Build list of matching device handles.
285 //
286
287 *NoHandles = 0;
288 for(Index=0;Index<NoBlockIoHandles;Index++) {
289 if (BlockIoBuffer[Index] != NULL) {
290 (*Buffer)[*NoHandles] = BlockIoBuffer[Index];
291 *NoHandles = *NoHandles + 1;
292 }
293 }
294
295 FreePool(BlockIoBuffer);
296
297 return EFI_SUCCESS;
298 }
299
300 EFI_FILE_HANDLE
LibOpenRoot(IN EFI_HANDLE DeviceHandle)301 LibOpenRoot (
302 IN EFI_HANDLE DeviceHandle
303 )
304 {
305 EFI_STATUS Status;
306 EFI_FILE_IO_INTERFACE *Volume;
307 EFI_FILE_HANDLE File;
308
309
310 //
311 // File the file system interface to the device
312 //
313
314 Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume);
315
316 //
317 // Open the root directory of the volume
318 //
319
320 if (!EFI_ERROR(Status)) {
321 Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File);
322 }
323
324 //
325 // Done
326 //
327
328 return EFI_ERROR(Status) ? NULL : File;
329 }
330
331 EFI_FILE_INFO *
LibFileInfo(IN EFI_FILE_HANDLE FHand)332 LibFileInfo (
333 IN EFI_FILE_HANDLE FHand
334 )
335 {
336 EFI_STATUS Status;
337 EFI_FILE_INFO *Buffer;
338 UINTN BufferSize;
339
340 //
341 // Initialize for GrowBuffer loop
342 //
343
344 Status = EFI_SUCCESS;
345 Buffer = NULL;
346 BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
347
348 //
349 // Call the real function
350 //
351
352 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
353 Status = uefi_call_wrapper(
354 FHand->GetInfo,
355 4,
356 FHand,
357 &GenericFileInfo,
358 &BufferSize,
359 Buffer
360 );
361 }
362
363 return Buffer;
364 }
365
366
367 EFI_FILE_SYSTEM_INFO *
LibFileSystemInfo(IN EFI_FILE_HANDLE FHand)368 LibFileSystemInfo (
369 IN EFI_FILE_HANDLE FHand
370 )
371 {
372 EFI_STATUS Status;
373 EFI_FILE_SYSTEM_INFO *Buffer;
374 UINTN BufferSize;
375
376 //
377 // Initialize for GrowBuffer loop
378 //
379
380 Status = EFI_SUCCESS;
381 Buffer = NULL;
382 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
383
384 //
385 // Call the real function
386 //
387
388 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
389 Status = uefi_call_wrapper(
390 FHand->GetInfo,
391 4,
392 FHand,
393 &FileSystemInfo,
394 &BufferSize,
395 Buffer
396 );
397 }
398
399 return Buffer;
400 }
401
402 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
LibFileSystemVolumeLabelInfo(IN EFI_FILE_HANDLE FHand)403 LibFileSystemVolumeLabelInfo (
404 IN EFI_FILE_HANDLE FHand
405 )
406 {
407 EFI_STATUS Status;
408 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
409 UINTN BufferSize;
410
411 //
412 // Initialize for GrowBuffer loop
413 //
414
415 Status = EFI_SUCCESS;
416 Buffer = NULL;
417 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
418
419 //
420 // Call the real function
421 //
422
423 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
424 Status = uefi_call_wrapper(
425 FHand->GetInfo,
426 4,
427 FHand,
428 &FileSystemVolumeLabelInfo,
429 &BufferSize,
430 Buffer
431 );
432 }
433
434 return Buffer;
435 }
436
437
438
439 EFI_STATUS
LibInstallProtocolInterfaces(IN OUT EFI_HANDLE * Handle,...)440 LibInstallProtocolInterfaces (
441 IN OUT EFI_HANDLE *Handle,
442 ...
443 )
444 {
445 va_list args;
446 EFI_STATUS Status;
447 EFI_GUID *Protocol;
448 VOID *Interface;
449 EFI_TPL OldTpl;
450 UINTN Index;
451 EFI_HANDLE OldHandle;
452
453 //
454 // Syncronize with notifcations
455 //
456
457 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
458 OldHandle = *Handle;
459
460 //
461 // Install the protocol interfaces
462 //
463
464 Index = 0;
465 Status = EFI_SUCCESS;
466 va_start (args, Handle);
467
468 while (!EFI_ERROR(Status)) {
469
470 //
471 // If protocol is NULL, then it's the end of the list
472 //
473
474 Protocol = va_arg(args, EFI_GUID *);
475 if (!Protocol) {
476 break;
477 }
478
479 Interface = va_arg(args, VOID *);
480
481 //
482 // Install it
483 //
484
485 DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface));
486 Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
487 if (EFI_ERROR(Status)) {
488 break;
489 }
490
491 Index += 1;
492 }
493 va_end (args);
494
495 va_end (args);
496
497 //
498 // If there was an error, remove all the interfaces that were
499 // installed without any errors
500 //
501
502 if (EFI_ERROR(Status)) {
503 va_start (args, Handle);
504 while (Index) {
505
506 Protocol = va_arg(args, EFI_GUID *);
507 Interface = va_arg(args, VOID *);
508 uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface);
509
510 Index -= 1;
511 }
512 va_end (args);
513
514 *Handle = OldHandle;
515 va_end (args);
516 }
517
518 //
519 // Done
520 //
521
522 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
523 return Status;
524 }
525
526
527 VOID
LibUninstallProtocolInterfaces(IN EFI_HANDLE Handle,...)528 LibUninstallProtocolInterfaces (
529 IN EFI_HANDLE Handle,
530 ...
531 )
532 {
533 va_list args;
534 EFI_STATUS Status;
535 EFI_GUID *Protocol;
536 VOID *Interface;
537
538
539 va_start (args, Handle);
540 for (; ;) {
541
542 //
543 // If protocol is NULL, then it's the end of the list
544 //
545
546 Protocol = va_arg(args, EFI_GUID *);
547 if (!Protocol) {
548 break;
549 }
550
551 Interface = va_arg(args, VOID *);
552
553 //
554 // Uninstall it
555 //
556
557 Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
558 if (EFI_ERROR(Status)) {
559 DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
560 }
561 }
562 va_end (args);
563 }
564
565
566 EFI_STATUS
LibReinstallProtocolInterfaces(IN OUT EFI_HANDLE * Handle,...)567 LibReinstallProtocolInterfaces (
568 IN OUT EFI_HANDLE *Handle,
569 ...
570 )
571 {
572 va_list args;
573 EFI_STATUS Status;
574 EFI_GUID *Protocol;
575 VOID *OldInterface, *NewInterface;
576 EFI_TPL OldTpl;
577 UINTN Index;
578
579 //
580 // Syncronize with notifcations
581 //
582
583 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
584
585 //
586 // Install the protocol interfaces
587 //
588
589 Index = 0;
590 Status = EFI_SUCCESS;
591 va_start (args, Handle);
592
593 while (!EFI_ERROR(Status)) {
594
595 //
596 // If protocol is NULL, then it's the end of the list
597 //
598
599 Protocol = va_arg(args, EFI_GUID *);
600 if (!Protocol) {
601 break;
602 }
603
604 OldInterface = va_arg(args, VOID *);
605 NewInterface = va_arg(args, VOID *);
606
607 //
608 // Reinstall it
609 //
610
611 Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
612 if (EFI_ERROR(Status)) {
613 break;
614 }
615
616 Index += 1;
617 }
618 va_end (args);
619
620 va_end (args);
621
622 //
623 // If there was an error, undo all the interfaces that were
624 // reinstalled without any errors
625 //
626
627 if (EFI_ERROR(Status)) {
628 va_start (args, Handle);
629 while (Index) {
630
631 Protocol = va_arg(args, EFI_GUID *);
632 OldInterface = va_arg(args, VOID *);
633 NewInterface = va_arg(args, VOID *);
634
635 uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
636
637 Index -= 1;
638 }
639 va_end (args);
640 }
641
642 //
643 // Done
644 //
645
646 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
647 return Status;
648 }
649