hand.c revision 1.1 1 /* $NetBSD: hand.c,v 1.1 2014/04/01 16:16:07 jakllsch 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
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
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
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 *Start, *Next, *DevPath;
123 HARDDRIVE_DEVICE_PATH *HardDriveDevicePath;
124 BOOLEAN Match;
125 BOOLEAN PreviousNodeIsHardDriveDevicePath;
126
127 //
128 // Initialize for GrowBuffer loop
129 //
130
131 BlockIoBuffer = NULL;
132 BufferSize = 50 * sizeof(EFI_HANDLE);
133
134 //
135 // Call the real function
136 //
137
138 while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) {
139
140 //
141 // Get list of device handles that support the BLOCK_IO Protocol.
142 //
143
144 Status = uefi_call_wrapper(
145 BS->LocateHandle,
146 5,
147 ByProtocol,
148 &BlockIoProtocol,
149 NULL,
150 &BufferSize,
151 BlockIoBuffer
152 );
153
154 }
155
156 NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE);
157 if (EFI_ERROR(Status)) {
158 NoBlockIoHandles = 0;
159 }
160
161 //
162 // If there was an error or there are no device handles that support
163 // the BLOCK_IO Protocol, then return.
164 //
165
166 if (NoBlockIoHandles == 0) {
167 FreePool(BlockIoBuffer);
168 *NoHandles = 0;
169 *Buffer = NULL;
170 return Status;
171 }
172
173 //
174 // Loop through all the device handles that support the BLOCK_IO Protocol
175 //
176
177 *NoHandles = 0;
178
179 for(Index=0;Index<NoBlockIoHandles;Index++) {
180
181 Status = uefi_call_wrapper(
182 BS->HandleProtocol,
183 3,
184 BlockIoBuffer[Index],
185 &DevicePathProtocol,
186 (VOID*)&DevicePath
187 );
188
189 //
190 // Search DevicePath for a Hard Drive Media Device Path node.
191 // If one is found, then see if it matches the signature that was
192 // passed in. If it does match, and the next node is the End of the
193 // device path, and the previous node is not a Hard Drive Media Device
194 // Path, then we have found a match.
195 //
196
197 Match = FALSE;
198
199 if (DevicePath != NULL) {
200
201 PreviousNodeIsHardDriveDevicePath = FALSE;
202
203 DevPath = DevicePath;
204 Start = DevPath;
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
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 *
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 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 *
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 Buffer = NULL;
380 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
381
382 //
383 // Call the real function
384 //
385
386 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
387 Status = uefi_call_wrapper(
388 FHand->GetInfo,
389 4,
390 FHand,
391 &FileSystemInfo,
392 &BufferSize,
393 Buffer
394 );
395 }
396
397 return Buffer;
398 }
399
400 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
401 LibFileSystemVolumeLabelInfo (
402 IN EFI_FILE_HANDLE FHand
403 )
404 {
405 EFI_STATUS Status;
406 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
407 UINTN BufferSize;
408
409 //
410 // Initialize for GrowBuffer loop
411 //
412
413 Buffer = NULL;
414 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
415
416 //
417 // Call the real function
418 //
419
420 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
421 Status = uefi_call_wrapper(
422 FHand->GetInfo,
423 4,
424 FHand,
425 &FileSystemVolumeLabelInfo,
426 &BufferSize,
427 Buffer
428 );
429 }
430
431 return Buffer;
432 }
433
434
435
436 EFI_STATUS
437 LibInstallProtocolInterfaces (
438 IN OUT EFI_HANDLE *Handle,
439 ...
440 )
441 {
442 va_list args;
443 EFI_STATUS Status;
444 EFI_GUID *Protocol;
445 VOID *Interface;
446 EFI_TPL OldTpl;
447 UINTN Index;
448 EFI_HANDLE OldHandle;
449
450 //
451 // Syncronize with notifcations
452 //
453
454 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
455 OldHandle = *Handle;
456
457 //
458 // Install the protocol interfaces
459 //
460
461 Index = 0;
462 Status = EFI_SUCCESS;
463 va_start (args, Handle);
464
465 while (!EFI_ERROR(Status)) {
466
467 //
468 // If protocol is NULL, then it's the end of the list
469 //
470
471 Protocol = va_arg(args, EFI_GUID *);
472 if (!Protocol) {
473 break;
474 }
475
476 Interface = va_arg(args, VOID *);
477
478 //
479 // Install it
480 //
481
482 DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface));
483 Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
484 if (EFI_ERROR(Status)) {
485 break;
486 }
487
488 Index += 1;
489 }
490
491 //
492 // If there was an error, remove all the interfaces that were
493 // installed without any errors
494 //
495
496 if (EFI_ERROR(Status)) {
497 va_start (args, Handle);
498 while (Index) {
499
500 Protocol = va_arg(args, EFI_GUID *);
501 Interface = va_arg(args, VOID *);
502 uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface);
503
504 Index -= 1;
505 }
506
507 *Handle = OldHandle;
508 }
509
510 //
511 // Done
512 //
513
514 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
515 return Status;
516 }
517
518
519 VOID
520 LibUninstallProtocolInterfaces (
521 IN EFI_HANDLE Handle,
522 ...
523 )
524 {
525 va_list args;
526 EFI_STATUS Status;
527 EFI_GUID *Protocol;
528 VOID *Interface;
529
530
531 va_start (args, Handle);
532 for (; ;) {
533
534 //
535 // If protocol is NULL, then it's the end of the list
536 //
537
538 Protocol = va_arg(args, EFI_GUID *);
539 if (!Protocol) {
540 break;
541 }
542
543 Interface = va_arg(args, VOID *);
544
545 //
546 // Uninstall it
547 //
548
549 Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
550 if (EFI_ERROR(Status)) {
551 DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
552 }
553 }
554 }
555
556
557 EFI_STATUS
558 LibReinstallProtocolInterfaces (
559 IN OUT EFI_HANDLE *Handle,
560 ...
561 )
562 {
563 va_list args;
564 EFI_STATUS Status;
565 EFI_GUID *Protocol;
566 VOID *OldInterface, *NewInterface;
567 EFI_TPL OldTpl;
568 UINTN Index;
569
570 //
571 // Syncronize with notifcations
572 //
573
574 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
575
576 //
577 // Install the protocol interfaces
578 //
579
580 Index = 0;
581 Status = EFI_SUCCESS;
582 va_start (args, Handle);
583
584 while (!EFI_ERROR(Status)) {
585
586 //
587 // If protocol is NULL, then it's the end of the list
588 //
589
590 Protocol = va_arg(args, EFI_GUID *);
591 if (!Protocol) {
592 break;
593 }
594
595 OldInterface = va_arg(args, VOID *);
596 NewInterface = va_arg(args, VOID *);
597
598 //
599 // Reinstall it
600 //
601
602 Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
603 if (EFI_ERROR(Status)) {
604 break;
605 }
606
607 Index += 1;
608 }
609
610 //
611 // If there was an error, undo all the interfaces that were
612 // reinstalled without any errors
613 //
614
615 if (EFI_ERROR(Status)) {
616 va_start (args, Handle);
617 while (Index) {
618
619 Protocol = va_arg(args, EFI_GUID *);
620 OldInterface = va_arg(args, VOID *);
621 NewInterface = va_arg(args, VOID *);
622
623 uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
624
625 Index -= 1;
626 }
627 }
628
629 //
630 // Done
631 //
632
633 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
634 return Status;
635 }
636