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