]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
MdeModulePkg/UDF: Fix creation of UDF logical partition
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / PartitionDxe / Partition.c
1 /** @file
2 Partition driver that produces logical BlockIo devices from a physical
3 BlockIo device. The logical BlockIo devices are based on the format
4 of the raw block devices media. Currently "El Torito CD-ROM", UDF, Legacy
5 MBR, and GPT partition schemes are supported.
6
7 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18
19 #include "Partition.h"
20
21 //
22 // Partition Driver Global Variables.
23 //
24 EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {
25 PartitionDriverBindingSupported,
26 PartitionDriverBindingStart,
27 PartitionDriverBindingStop,
28 //
29 // Grub4Dos copies the BPB of the first partition to the MBR. If the
30 // DriverBindingStart() of the Fat driver gets run before that of Partition
31 // driver only the first partition can be recognized.
32 // Let the driver binding version of Partition driver be higher than that of
33 // Fat driver to make sure the DriverBindingStart() of the Partition driver
34 // gets run before that of Fat driver so that all the partitions can be recognized.
35 //
36 0xb,
37 NULL,
38 NULL
39 };
40
41 //
42 // Prioritized function list to detect partition table.
43 //
44 PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
45 PartitionInstallGptChildHandles,
46 PartitionInstallElToritoChildHandles,
47 PartitionInstallMbrChildHandles,
48 PartitionInstallUdfChildHandles,
49 NULL
50 };
51
52 /**
53 Test to see if this driver supports ControllerHandle. Any ControllerHandle
54 than contains a BlockIo and DiskIo protocol or a BlockIo2 protocol can be
55 supported.
56
57 @param[in] This Protocol instance pointer.
58 @param[in] ControllerHandle Handle of device to test.
59 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
60 device to start.
61
62 @retval EFI_SUCCESS This driver supports this device
63 @retval EFI_ALREADY_STARTED This driver is already running on this device
64 @retval other This driver does not support this device
65
66 **/
67 EFI_STATUS
68 EFIAPI
69 PartitionDriverBindingSupported (
70 IN EFI_DRIVER_BINDING_PROTOCOL *This,
71 IN EFI_HANDLE ControllerHandle,
72 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
73 )
74 {
75 EFI_STATUS Status;
76 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
77 EFI_DISK_IO_PROTOCOL *DiskIo;
78 EFI_DEV_PATH *Node;
79
80 //
81 // Check RemainingDevicePath validation
82 //
83 if (RemainingDevicePath != NULL) {
84 //
85 // Check if RemainingDevicePath is the End of Device Path Node,
86 // if yes, go on checking other conditions
87 //
88 if (!IsDevicePathEnd (RemainingDevicePath)) {
89 //
90 // If RemainingDevicePath isn't the End of Device Path Node,
91 // check its validation
92 //
93 Node = (EFI_DEV_PATH *) RemainingDevicePath;
94 if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||
95 Node->DevPath.SubType != MEDIA_HARDDRIVE_DP ||
96 DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)) {
97 return EFI_UNSUPPORTED;
98 }
99 }
100 }
101
102 //
103 // Open the IO Abstraction(s) needed to perform the supported test
104 //
105 Status = gBS->OpenProtocol (
106 ControllerHandle,
107 &gEfiDiskIoProtocolGuid,
108 (VOID **) &DiskIo,
109 This->DriverBindingHandle,
110 ControllerHandle,
111 EFI_OPEN_PROTOCOL_BY_DRIVER
112 );
113 if (Status == EFI_ALREADY_STARTED) {
114 return EFI_SUCCESS;
115 }
116 if (EFI_ERROR (Status)) {
117 return Status;
118 }
119 //
120 // Close the I/O Abstraction(s) used to perform the supported test
121 //
122 gBS->CloseProtocol (
123 ControllerHandle,
124 &gEfiDiskIoProtocolGuid,
125 This->DriverBindingHandle,
126 ControllerHandle
127 );
128
129 //
130 // Open the EFI Device Path protocol needed to perform the supported test
131 //
132 Status = gBS->OpenProtocol (
133 ControllerHandle,
134 &gEfiDevicePathProtocolGuid,
135 (VOID **) &ParentDevicePath,
136 This->DriverBindingHandle,
137 ControllerHandle,
138 EFI_OPEN_PROTOCOL_BY_DRIVER
139 );
140 if (Status == EFI_ALREADY_STARTED) {
141 return EFI_SUCCESS;
142 }
143
144 if (EFI_ERROR (Status)) {
145 return Status;
146 }
147
148 //
149 // Close protocol, don't use device path protocol in the Support() function
150 //
151 gBS->CloseProtocol (
152 ControllerHandle,
153 &gEfiDevicePathProtocolGuid,
154 This->DriverBindingHandle,
155 ControllerHandle
156 );
157
158 //
159 // Open the IO Abstraction(s) needed to perform the supported test
160 //
161 Status = gBS->OpenProtocol (
162 ControllerHandle,
163 &gEfiBlockIoProtocolGuid,
164 NULL,
165 This->DriverBindingHandle,
166 ControllerHandle,
167 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
168 );
169
170 return Status;
171 }
172
173 /**
174 Start this driver on ControllerHandle by opening a Block IO or a Block IO2
175 or both, and Disk IO protocol, reading Device Path, and creating a child
176 handle with a Disk IO and device path protocol.
177
178 @param[in] This Protocol instance pointer.
179 @param[in] ControllerHandle Handle of device to bind driver to
180 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
181 device to start.
182
183 @retval EFI_SUCCESS This driver is added to ControllerHandle
184 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
185 @retval other This driver does not support this device
186
187 **/
188 EFI_STATUS
189 EFIAPI
190 PartitionDriverBindingStart (
191 IN EFI_DRIVER_BINDING_PROTOCOL *This,
192 IN EFI_HANDLE ControllerHandle,
193 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
194 )
195 {
196 EFI_STATUS Status;
197 EFI_STATUS OpenStatus;
198 EFI_BLOCK_IO_PROTOCOL *BlockIo;
199 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
200 EFI_DISK_IO_PROTOCOL *DiskIo;
201 EFI_DISK_IO2_PROTOCOL *DiskIo2;
202 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
203 PARTITION_DETECT_ROUTINE *Routine;
204 BOOLEAN MediaPresent;
205 EFI_TPL OldTpl;
206
207 BlockIo2 = NULL;
208 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
209 //
210 // Check RemainingDevicePath validation
211 //
212 if (RemainingDevicePath != NULL) {
213 //
214 // Check if RemainingDevicePath is the End of Device Path Node,
215 // if yes, return EFI_SUCCESS
216 //
217 if (IsDevicePathEnd (RemainingDevicePath)) {
218 Status = EFI_SUCCESS;
219 goto Exit;
220 }
221 }
222
223 //
224 // Try to open BlockIO and BlockIO2. If BlockIO would be opened, continue,
225 // otherwise, return error.
226 //
227 Status = gBS->OpenProtocol (
228 ControllerHandle,
229 &gEfiBlockIoProtocolGuid,
230 (VOID **) &BlockIo,
231 This->DriverBindingHandle,
232 ControllerHandle,
233 EFI_OPEN_PROTOCOL_GET_PROTOCOL
234 );
235 if (EFI_ERROR (Status)) {
236 goto Exit;
237 }
238
239 Status = gBS->OpenProtocol (
240 ControllerHandle,
241 &gEfiBlockIo2ProtocolGuid,
242 (VOID **) &BlockIo2,
243 This->DriverBindingHandle,
244 ControllerHandle,
245 EFI_OPEN_PROTOCOL_GET_PROTOCOL
246 );
247 if (EFI_ERROR (Status)) {
248 BlockIo2 = NULL;
249 }
250
251 //
252 // Get the Device Path Protocol on ControllerHandle's handle.
253 //
254 Status = gBS->OpenProtocol (
255 ControllerHandle,
256 &gEfiDevicePathProtocolGuid,
257 (VOID **) &ParentDevicePath,
258 This->DriverBindingHandle,
259 ControllerHandle,
260 EFI_OPEN_PROTOCOL_BY_DRIVER
261 );
262 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
263 goto Exit;
264 }
265
266 //
267 // Get the DiskIo and DiskIo2.
268 //
269 Status = gBS->OpenProtocol (
270 ControllerHandle,
271 &gEfiDiskIoProtocolGuid,
272 (VOID **) &DiskIo,
273 This->DriverBindingHandle,
274 ControllerHandle,
275 EFI_OPEN_PROTOCOL_BY_DRIVER
276 );
277 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
278 gBS->CloseProtocol (
279 ControllerHandle,
280 &gEfiDevicePathProtocolGuid,
281 This->DriverBindingHandle,
282 ControllerHandle
283 );
284 goto Exit;
285 }
286
287 OpenStatus = Status;
288
289 Status = gBS->OpenProtocol (
290 ControllerHandle,
291 &gEfiDiskIo2ProtocolGuid,
292 (VOID **) &DiskIo2,
293 This->DriverBindingHandle,
294 ControllerHandle,
295 EFI_OPEN_PROTOCOL_BY_DRIVER
296 );
297 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
298 DiskIo2 = NULL;
299 }
300
301 //
302 // Try to read blocks when there's media or it is removable physical partition.
303 //
304 Status = EFI_UNSUPPORTED;
305 MediaPresent = BlockIo->Media->MediaPresent;
306 if (BlockIo->Media->MediaPresent ||
307 (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) {
308 //
309 // Try for GPT, then El Torito, then UDF, and then legacy MBR partition
310 // types. If the media supports a given partition type install child handles
311 // to represent the partitions described by the media.
312 //
313 Routine = &mPartitionDetectRoutineTable[0];
314 while (*Routine != NULL) {
315 Status = (*Routine) (
316 This,
317 ControllerHandle,
318 DiskIo,
319 DiskIo2,
320 BlockIo,
321 BlockIo2,
322 ParentDevicePath
323 );
324 if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {
325 break;
326 }
327 Routine++;
328 }
329 }
330 //
331 // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),
332 // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the
333 // driver. So don't try to close them. Otherwise, we will break the dependency
334 // between the controller and the driver set up before.
335 //
336 // In the case that when the media changes on a device it will Reinstall the
337 // BlockIo interaface. This will cause a call to our Stop(), and a subsequent
338 // reentrant call to our Start() successfully. We should leave the device open
339 // when this happen. The "media change" case includes either the status is
340 // EFI_MEDIA_CHANGED or it is a "media" to "no media" change.
341 //
342 if (EFI_ERROR (Status) &&
343 !EFI_ERROR (OpenStatus) &&
344 Status != EFI_MEDIA_CHANGED &&
345 !(MediaPresent && Status == EFI_NO_MEDIA)) {
346 gBS->CloseProtocol (
347 ControllerHandle,
348 &gEfiDiskIoProtocolGuid,
349 This->DriverBindingHandle,
350 ControllerHandle
351 );
352 //
353 // Close Parent DiskIo2 if has.
354 //
355 gBS->CloseProtocol (
356 ControllerHandle,
357 &gEfiDiskIo2ProtocolGuid,
358 This->DriverBindingHandle,
359 ControllerHandle
360 );
361
362 gBS->CloseProtocol (
363 ControllerHandle,
364 &gEfiDevicePathProtocolGuid,
365 This->DriverBindingHandle,
366 ControllerHandle
367 );
368 }
369
370 Exit:
371 gBS->RestoreTPL (OldTpl);
372 return Status;
373 }
374
375 /**
376 Stop this driver on ControllerHandle. Support stopping any child handles
377 created by this driver.
378
379 @param This Protocol instance pointer.
380 @param ControllerHandle Handle of device to stop driver on
381 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
382 children is zero stop the entire bus driver.
383 @param ChildHandleBuffer List of Child Handles to Stop.
384
385 @retval EFI_SUCCESS This driver is removed ControllerHandle
386 @retval other This driver was not removed from this device
387
388 **/
389 EFI_STATUS
390 EFIAPI
391 PartitionDriverBindingStop (
392 IN EFI_DRIVER_BINDING_PROTOCOL *This,
393 IN EFI_HANDLE ControllerHandle,
394 IN UINTN NumberOfChildren,
395 IN EFI_HANDLE *ChildHandleBuffer
396 )
397 {
398 EFI_STATUS Status;
399 UINTN Index;
400 EFI_BLOCK_IO_PROTOCOL *BlockIo;
401 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
402 BOOLEAN AllChildrenStopped;
403 PARTITION_PRIVATE_DATA *Private;
404 EFI_DISK_IO_PROTOCOL *DiskIo;
405
406 BlockIo = NULL;
407 BlockIo2 = NULL;
408 Private = NULL;
409
410 if (NumberOfChildren == 0) {
411 //
412 // In the case of re-entry of the PartitionDriverBindingStop, the
413 // NumberOfChildren may not reflect the actual number of children on the
414 // bus driver. Hence, additional check is needed here.
415 //
416 if (HasChildren (ControllerHandle)) {
417 DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: Still has child.\n"));
418 return EFI_DEVICE_ERROR;
419 }
420
421 //
422 // Close the bus driver
423 //
424 gBS->CloseProtocol (
425 ControllerHandle,
426 &gEfiDiskIoProtocolGuid,
427 This->DriverBindingHandle,
428 ControllerHandle
429 );
430 //
431 // Close Parent BlockIO2 if has.
432 //
433 gBS->CloseProtocol (
434 ControllerHandle,
435 &gEfiDiskIo2ProtocolGuid,
436 This->DriverBindingHandle,
437 ControllerHandle
438 );
439
440 gBS->CloseProtocol (
441 ControllerHandle,
442 &gEfiDevicePathProtocolGuid,
443 This->DriverBindingHandle,
444 ControllerHandle
445 );
446 return EFI_SUCCESS;
447 }
448
449 AllChildrenStopped = TRUE;
450 for (Index = 0; Index < NumberOfChildren; Index++) {
451 gBS->OpenProtocol (
452 ChildHandleBuffer[Index],
453 &gEfiBlockIoProtocolGuid,
454 (VOID **) &BlockIo,
455 This->DriverBindingHandle,
456 ControllerHandle,
457 EFI_OPEN_PROTOCOL_GET_PROTOCOL
458 );
459 //
460 // Try to locate BlockIo2.
461 //
462 gBS->OpenProtocol (
463 ChildHandleBuffer[Index],
464 &gEfiBlockIo2ProtocolGuid,
465 (VOID **) &BlockIo2,
466 This->DriverBindingHandle,
467 ControllerHandle,
468 EFI_OPEN_PROTOCOL_GET_PROTOCOL
469 );
470
471
472 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
473 if (Private->InStop) {
474 //
475 // If the child handle is going to be stopped again during the re-entry
476 // of DriverBindingStop, just do nothing.
477 //
478 break;
479 }
480 Private->InStop = TRUE;
481
482 BlockIo->FlushBlocks (BlockIo);
483
484 if (BlockIo2 != NULL) {
485 Status = BlockIo2->FlushBlocksEx (BlockIo2, NULL);
486 DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: FlushBlocksEx returned with %r\n", Status));
487 } else {
488 Status = EFI_SUCCESS;
489 }
490
491 gBS->CloseProtocol (
492 ControllerHandle,
493 &gEfiDiskIoProtocolGuid,
494 This->DriverBindingHandle,
495 ChildHandleBuffer[Index]
496 );
497 //
498 // All Software protocols have be freed from the handle so remove it.
499 // Remove the BlockIo Protocol if has.
500 // Remove the BlockIo2 Protocol if has.
501 //
502 if (BlockIo2 != NULL) {
503 //
504 // Some device drivers might re-install the BlockIO(2) protocols for a
505 // media change condition. Therefore, if the FlushBlocksEx returned with
506 // EFI_MEDIA_CHANGED, just let the BindingStop fail to avoid potential
507 // reference of already stopped child handle.
508 //
509 if (Status != EFI_MEDIA_CHANGED) {
510 Status = gBS->UninstallMultipleProtocolInterfaces (
511 ChildHandleBuffer[Index],
512 &gEfiDevicePathProtocolGuid,
513 Private->DevicePath,
514 &gEfiBlockIoProtocolGuid,
515 &Private->BlockIo,
516 &gEfiBlockIo2ProtocolGuid,
517 &Private->BlockIo2,
518 &gEfiPartitionInfoProtocolGuid,
519 &Private->PartitionInfo,
520 Private->EspGuid,
521 NULL,
522 NULL
523 );
524 }
525 } else {
526 Status = gBS->UninstallMultipleProtocolInterfaces (
527 ChildHandleBuffer[Index],
528 &gEfiDevicePathProtocolGuid,
529 Private->DevicePath,
530 &gEfiBlockIoProtocolGuid,
531 &Private->BlockIo,
532 &gEfiPartitionInfoProtocolGuid,
533 &Private->PartitionInfo,
534 Private->EspGuid,
535 NULL,
536 NULL
537 );
538 }
539
540 if (EFI_ERROR (Status)) {
541 Private->InStop = FALSE;
542 gBS->OpenProtocol (
543 ControllerHandle,
544 &gEfiDiskIoProtocolGuid,
545 (VOID **) &DiskIo,
546 This->DriverBindingHandle,
547 ChildHandleBuffer[Index],
548 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
549 );
550 } else {
551 FreePool (Private->DevicePath);
552 FreePool (Private);
553 }
554
555 if (EFI_ERROR (Status)) {
556 AllChildrenStopped = FALSE;
557 if (Status == EFI_MEDIA_CHANGED) {
558 break;
559 }
560 }
561 }
562
563 if (!AllChildrenStopped) {
564 return EFI_DEVICE_ERROR;
565 }
566
567 return EFI_SUCCESS;
568 }
569
570
571 /**
572 Reset the Block Device.
573
574 @param This Protocol instance pointer.
575 @param ExtendedVerification Driver may perform diagnostics on reset.
576
577 @retval EFI_SUCCESS The device was reset.
578 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
579 not be reset.
580
581 **/
582 EFI_STATUS
583 EFIAPI
584 PartitionReset (
585 IN EFI_BLOCK_IO_PROTOCOL *This,
586 IN BOOLEAN ExtendedVerification
587 )
588 {
589 PARTITION_PRIVATE_DATA *Private;
590
591 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
592
593 return Private->ParentBlockIo->Reset (
594 Private->ParentBlockIo,
595 ExtendedVerification
596 );
597 }
598
599 /**
600 Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
601 for no media or media change case. Otherwise DefaultStatus is returned.
602
603 @param DiskIo Pointer to the DiskIo instance.
604 @param MediaId Id of the media, changes every time the media is replaced.
605 @param DefaultStatus The default status to return when it's not the no media
606 or media change case.
607
608 @retval EFI_NO_MEDIA There is no media.
609 @retval EFI_MEDIA_CHANGED The media was changed.
610 @retval others The default status to return.
611 **/
612 EFI_STATUS
613 ProbeMediaStatus (
614 IN EFI_DISK_IO_PROTOCOL *DiskIo,
615 IN UINT32 MediaId,
616 IN EFI_STATUS DefaultStatus
617 )
618 {
619 EFI_STATUS Status;
620 UINT8 Buffer[1];
621
622 //
623 // Read 1 byte from offset 0 to check if the MediaId is still valid.
624 // The reading operation is synchronious thus it is not worth it to
625 // allocate a buffer from the pool. The destination buffer for the
626 // data is in the stack.
627 //
628 Status = DiskIo->ReadDisk (DiskIo, MediaId, 0, 1, (VOID*)Buffer);
629 if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
630 return Status;
631 }
632 return DefaultStatus;
633 }
634
635 /**
636 Read by using the Disk IO protocol on the parent device. Lba addresses
637 must be converted to byte offsets.
638
639 @param This Protocol instance pointer.
640 @param MediaId Id of the media, changes every time the media is replaced.
641 @param Lba The starting Logical Block Address to read from
642 @param BufferSize Size of Buffer, must be a multiple of device block size.
643 @param Buffer Buffer containing read data
644
645 @retval EFI_SUCCESS The data was read correctly from the device.
646 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
647 @retval EFI_NO_MEDIA There is no media in the device.
648 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
649 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
650 @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
651 valid for the device.
652
653 **/
654 EFI_STATUS
655 EFIAPI
656 PartitionReadBlocks (
657 IN EFI_BLOCK_IO_PROTOCOL *This,
658 IN UINT32 MediaId,
659 IN EFI_LBA Lba,
660 IN UINTN BufferSize,
661 OUT VOID *Buffer
662 )
663 {
664 PARTITION_PRIVATE_DATA *Private;
665 UINT64 Offset;
666
667 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
668
669 if (BufferSize % Private->BlockSize != 0) {
670 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
671 }
672
673 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
674 if (Offset + BufferSize > Private->End) {
675 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
676 }
677 //
678 // Because some kinds of partition have different block size from their parent
679 // device, we call the Disk IO protocol on the parent device, not the Block IO
680 // protocol
681 //
682 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
683 }
684
685 /**
686 Write by using the Disk IO protocol on the parent device. Lba addresses
687 must be converted to byte offsets.
688
689 @param[in] This Protocol instance pointer.
690 @param[in] MediaId Id of the media, changes every time the media is replaced.
691 @param[in] Lba The starting Logical Block Address to read from
692 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
693 @param[in] Buffer Buffer containing data to be written to device.
694
695 @retval EFI_SUCCESS The data was written correctly to the device.
696 @retval EFI_WRITE_PROTECTED The device can not be written to.
697 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
698 @retval EFI_NO_MEDIA There is no media in the device.
699 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
700 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
701 @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not
702 valid for the device.
703
704 **/
705 EFI_STATUS
706 EFIAPI
707 PartitionWriteBlocks (
708 IN EFI_BLOCK_IO_PROTOCOL *This,
709 IN UINT32 MediaId,
710 IN EFI_LBA Lba,
711 IN UINTN BufferSize,
712 IN VOID *Buffer
713 )
714 {
715 PARTITION_PRIVATE_DATA *Private;
716 UINT64 Offset;
717
718 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
719
720 if (BufferSize % Private->BlockSize != 0) {
721 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
722 }
723
724 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
725 if (Offset + BufferSize > Private->End) {
726 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
727 }
728 //
729 // Because some kinds of partition have different block size from their parent
730 // device, we call the Disk IO protocol on the parent device, not the Block IO
731 // protocol
732 //
733 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
734 }
735
736
737 /**
738 Flush the parent Block Device.
739
740 @param This Protocol instance pointer.
741
742 @retval EFI_SUCCESS All outstanding data was written to the device
743 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
744 @retval EFI_NO_MEDIA There is no media in the device.
745
746 **/
747 EFI_STATUS
748 EFIAPI
749 PartitionFlushBlocks (
750 IN EFI_BLOCK_IO_PROTOCOL *This
751 )
752 {
753 PARTITION_PRIVATE_DATA *Private;
754
755 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
756
757 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
758 }
759
760 /**
761 Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
762 for no media or media change case. Otherwise DefaultStatus is returned.
763
764 @param DiskIo2 Pointer to the DiskIo2 instance.
765 @param MediaId Id of the media, changes every time the media is replaced.
766 @param DefaultStatus The default status to return when it's not the no media
767 or media change case.
768
769 @retval EFI_NO_MEDIA There is no media.
770 @retval EFI_MEDIA_CHANGED The media was changed.
771 @retval others The default status to return.
772 **/
773 EFI_STATUS
774 ProbeMediaStatusEx (
775 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
776 IN UINT32 MediaId,
777 IN EFI_STATUS DefaultStatus
778 )
779 {
780 EFI_STATUS Status;
781
782 //
783 // Read 1 byte from offset 0 but passing NULL as buffer pointer
784 //
785 Status = DiskIo2->ReadDiskEx (DiskIo2, MediaId, 0, NULL, 1, NULL);
786 if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
787 return Status;
788 }
789 return DefaultStatus;
790 }
791
792 /**
793 Reset the Block Device throught Block I/O2 protocol.
794
795 @param This Protocol instance pointer.
796 @param ExtendedVerification Driver may perform diagnostics on reset.
797
798 @retval EFI_SUCCESS The device was reset.
799 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
800 not be reset.
801
802 **/
803 EFI_STATUS
804 EFIAPI
805 PartitionResetEx (
806 IN EFI_BLOCK_IO2_PROTOCOL *This,
807 IN BOOLEAN ExtendedVerification
808 )
809 {
810 PARTITION_PRIVATE_DATA *Private;
811
812 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
813
814 return Private->ParentBlockIo2->Reset (
815 Private->ParentBlockIo2,
816 ExtendedVerification
817 );
818 }
819
820 /**
821 The general callback for the DiskIo2 interfaces.
822 @param Event Event whose notification function is being invoked.
823 @param Context The pointer to the notification function's context,
824 which points to the PARTITION_ACCESS_TASK instance.
825 **/
826 VOID
827 EFIAPI
828 PartitionOnAccessComplete (
829 IN EFI_EVENT Event,
830 IN VOID *Context
831 )
832 {
833 PARTITION_ACCESS_TASK *Task;
834
835 Task = (PARTITION_ACCESS_TASK *) Context;
836
837 gBS->CloseEvent (Event);
838
839 Task->BlockIo2Token->TransactionStatus = Task->DiskIo2Token.TransactionStatus;
840 gBS->SignalEvent (Task->BlockIo2Token->Event);
841
842 FreePool (Task);
843 }
844
845 /**
846 Create a new PARTITION_ACCESS_TASK instance.
847
848 @param Token Pointer to the EFI_BLOCK_IO2_TOKEN.
849
850 @return Pointer to the created PARTITION_ACCESS_TASK instance or NULL upon failure.
851 **/
852 PARTITION_ACCESS_TASK *
853 PartitionCreateAccessTask (
854 IN EFI_BLOCK_IO2_TOKEN *Token
855 )
856 {
857 EFI_STATUS Status;
858 PARTITION_ACCESS_TASK *Task;
859
860 Task = AllocatePool (sizeof (*Task));
861 if (Task == NULL) {
862 return NULL;
863 }
864
865 Status = gBS->CreateEvent (
866 EVT_NOTIFY_SIGNAL,
867 TPL_NOTIFY,
868 PartitionOnAccessComplete,
869 Task,
870 &Task->DiskIo2Token.Event
871 );
872 if (EFI_ERROR (Status)) {
873 FreePool (Task);
874 return NULL;
875 }
876
877 Task->BlockIo2Token = Token;
878
879 return Task;
880 }
881
882 /**
883 Read BufferSize bytes from Lba into Buffer.
884
885 This function reads the requested number of blocks from the device. All the
886 blocks are read, or an error is returned.
887 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
888 non-blocking I/O is being used, the Event associated with this request will
889 not be signaled.
890
891 @param[in] This Indicates a pointer to the calling context.
892 @param[in] MediaId Id of the media, changes every time the media is
893 replaced.
894 @param[in] Lba The starting Logical Block Address to read from.
895 @param[in, out] Token A pointer to the token associated with the transaction.
896 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
897 @param[out] Buffer A pointer to the destination buffer for the data. The
898 caller is responsible for either having implicit or
899 explicit ownership of the buffer.
900
901 @retval EFI_SUCCESS The read request was queued if Token->Event is
902 not NULL.The data was read correctly from the
903 device if the Token->Event is NULL.
904 @retval EFI_DEVICE_ERROR The device reported an error while performing
905 the read.
906 @retval EFI_NO_MEDIA There is no media in the device.
907 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
908 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
909 intrinsic block size of the device.
910 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
911 or the buffer is not on proper alignment.
912 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
913 of resources.
914 **/
915 EFI_STATUS
916 EFIAPI
917 PartitionReadBlocksEx (
918 IN EFI_BLOCK_IO2_PROTOCOL *This,
919 IN UINT32 MediaId,
920 IN EFI_LBA Lba,
921 IN OUT EFI_BLOCK_IO2_TOKEN *Token,
922 IN UINTN BufferSize,
923 OUT VOID *Buffer
924 )
925 {
926 EFI_STATUS Status;
927 PARTITION_PRIVATE_DATA *Private;
928 UINT64 Offset;
929 PARTITION_ACCESS_TASK *Task;
930
931 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
932
933 if (BufferSize % Private->BlockSize != 0) {
934 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
935 }
936
937 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
938 if (Offset + BufferSize > Private->End) {
939 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
940 }
941
942 if ((Token != NULL) && (Token->Event != NULL)) {
943 Task = PartitionCreateAccessTask (Token);
944 if (Task == NULL) {
945 return EFI_OUT_OF_RESOURCES;
946 }
947
948 Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
949 if (EFI_ERROR (Status)) {
950 gBS->CloseEvent (Task->DiskIo2Token.Event);
951 FreePool (Task);
952 }
953 } else {
954 Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
955 }
956
957 return Status;
958 }
959
960 /**
961 Write BufferSize bytes from Lba into Buffer.
962
963 This function writes the requested number of blocks to the device. All blocks
964 are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
965 EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
966 being used, the Event associated with this request will not be signaled.
967
968 @param[in] This Indicates a pointer to the calling context.
969 @param[in] MediaId The media ID that the write request is for.
970 @param[in] Lba The starting logical block address to be written. The
971 caller is responsible for writing to only legitimate
972 locations.
973 @param[in, out] Token A pointer to the token associated with the transaction.
974 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
975 @param[in] Buffer A pointer to the source buffer for the data.
976
977 @retval EFI_SUCCESS The write request was queued if Event is not NULL.
978 The data was written correctly to the device if
979 the Event is NULL.
980 @retval EFI_WRITE_PROTECTED The device can not be written to.
981 @retval EFI_NO_MEDIA There is no media in the device.
982 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
983 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
984 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
985 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
986 or the buffer is not on proper alignment.
987 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
988 of resources.
989
990 **/
991 EFI_STATUS
992 EFIAPI
993 PartitionWriteBlocksEx (
994 IN EFI_BLOCK_IO2_PROTOCOL *This,
995 IN UINT32 MediaId,
996 IN EFI_LBA Lba,
997 IN OUT EFI_BLOCK_IO2_TOKEN *Token,
998 IN UINTN BufferSize,
999 IN VOID *Buffer
1000 )
1001 {
1002 EFI_STATUS Status;
1003 PARTITION_PRIVATE_DATA *Private;
1004 UINT64 Offset;
1005 PARTITION_ACCESS_TASK *Task;
1006
1007 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
1008
1009 if (BufferSize % Private->BlockSize != 0) {
1010 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
1011 }
1012
1013 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
1014 if (Offset + BufferSize > Private->End) {
1015 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
1016 }
1017
1018 if ((Token != NULL) && (Token->Event != NULL)) {
1019 Task = PartitionCreateAccessTask (Token);
1020 if (Task == NULL) {
1021 return EFI_OUT_OF_RESOURCES;
1022 }
1023
1024 Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
1025 if (EFI_ERROR (Status)) {
1026 gBS->CloseEvent (Task->DiskIo2Token.Event);
1027 FreePool (Task);
1028 }
1029 } else {
1030 Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
1031 }
1032 return Status;
1033 }
1034
1035 /**
1036 Flush the Block Device.
1037
1038 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
1039 is returned and non-blocking I/O is being used, the Event associated with
1040 this request will not be signaled.
1041
1042 @param[in] This Indicates a pointer to the calling context.
1043 @param[in, out] Token A pointer to the token associated with the transaction
1044
1045 @retval EFI_SUCCESS The flush request was queued if Event is not NULL.
1046 All outstanding data was written correctly to the
1047 device if the Event is NULL.
1048 @retval EFI_DEVICE_ERROR The device reported an error while writting back
1049 the data.
1050 @retval EFI_WRITE_PROTECTED The device cannot be written to.
1051 @retval EFI_NO_MEDIA There is no media in the device.
1052 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1053 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1054 of resources.
1055
1056 **/
1057 EFI_STATUS
1058 EFIAPI
1059 PartitionFlushBlocksEx (
1060 IN EFI_BLOCK_IO2_PROTOCOL *This,
1061 IN OUT EFI_BLOCK_IO2_TOKEN *Token
1062 )
1063 {
1064 EFI_STATUS Status;
1065 PARTITION_PRIVATE_DATA *Private;
1066 PARTITION_ACCESS_TASK *Task;
1067
1068 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
1069
1070 if ((Token != NULL) && (Token->Event != NULL)) {
1071 Task = PartitionCreateAccessTask (Token);
1072 if (Task == NULL) {
1073 return EFI_OUT_OF_RESOURCES;
1074 }
1075
1076 Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, &Task->DiskIo2Token);
1077 if (EFI_ERROR (Status)) {
1078 gBS->CloseEvent (Task->DiskIo2Token.Event);
1079 FreePool (Task);
1080 }
1081 } else {
1082 Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, NULL);
1083 }
1084 return Status;
1085 }
1086
1087
1088 /**
1089 Create a child handle for a logical block device that represents the
1090 bytes Start to End of the Parent Block IO device.
1091
1092 @param[in] This Protocol instance pointer.
1093 @param[in] ParentHandle Parent Handle for new child.
1094 @param[in] ParentDiskIo Parent DiskIo interface.
1095 @param[in] ParentDiskIo2 Parent DiskIo2 interface.
1096 @param[in] ParentBlockIo Parent BlockIo interface.
1097 @param[in] ParentBlockIo2 Parent BlockIo2 interface.
1098 @param[in] ParentDevicePath Parent Device Path.
1099 @param[in] DevicePathNode Child Device Path node.
1100 @param[in] PartitionInfo Child Partition Information interface.
1101 @param[in] Start Start Block.
1102 @param[in] End End Block.
1103 @param[in] BlockSize Child block size.
1104
1105 @retval EFI_SUCCESS A child handle was added.
1106 @retval other A child handle was not added.
1107
1108 **/
1109 EFI_STATUS
1110 PartitionInstallChildHandle (
1111 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1112 IN EFI_HANDLE ParentHandle,
1113 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
1114 IN EFI_DISK_IO2_PROTOCOL *ParentDiskIo2,
1115 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
1116 IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2,
1117 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
1118 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
1119 IN EFI_PARTITION_INFO_PROTOCOL *PartitionInfo,
1120 IN EFI_LBA Start,
1121 IN EFI_LBA End,
1122 IN UINT32 BlockSize
1123 )
1124 {
1125 EFI_STATUS Status;
1126 PARTITION_PRIVATE_DATA *Private;
1127
1128 Status = EFI_SUCCESS;
1129 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));
1130 if (Private == NULL) {
1131 return EFI_OUT_OF_RESOURCES;
1132 }
1133
1134 Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;
1135
1136 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);
1137 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);
1138
1139 Private->BlockSize = BlockSize;
1140 Private->ParentBlockIo = ParentBlockIo;
1141 Private->ParentBlockIo2 = ParentBlockIo2;
1142 Private->DiskIo = ParentDiskIo;
1143 Private->DiskIo2 = ParentDiskIo2;
1144
1145 //
1146 // Set the BlockIO into Private Data.
1147 //
1148 Private->BlockIo.Revision = ParentBlockIo->Revision;
1149
1150 Private->BlockIo.Media = &Private->Media;
1151 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
1152
1153 Private->BlockIo.Reset = PartitionReset;
1154 Private->BlockIo.ReadBlocks = PartitionReadBlocks;
1155 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;
1156 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;
1157
1158 //
1159 // Set the BlockIO2 into Private Data.
1160 //
1161 if (Private->DiskIo2 != NULL) {
1162 ASSERT (Private->ParentBlockIo2 != NULL);
1163 Private->BlockIo2.Media = &Private->Media2;
1164 CopyMem (Private->BlockIo2.Media, ParentBlockIo2->Media, sizeof (EFI_BLOCK_IO_MEDIA));
1165
1166 Private->BlockIo2.Reset = PartitionResetEx;
1167 Private->BlockIo2.ReadBlocksEx = PartitionReadBlocksEx;
1168 Private->BlockIo2.WriteBlocksEx = PartitionWriteBlocksEx;
1169 Private->BlockIo2.FlushBlocksEx = PartitionFlushBlocksEx;
1170 }
1171
1172 Private->Media.IoAlign = 0;
1173 Private->Media.LogicalPartition = TRUE;
1174 Private->Media.LastBlock = DivU64x32 (
1175 MultU64x32 (
1176 End - Start + 1,
1177 ParentBlockIo->Media->BlockSize
1178 ),
1179 BlockSize
1180 ) - 1;
1181
1182 Private->Media.BlockSize = (UINT32) BlockSize;
1183
1184 Private->Media2.IoAlign = 0;
1185 Private->Media2.LogicalPartition = TRUE;
1186 Private->Media2.LastBlock = Private->Media.LastBlock;
1187 Private->Media2.BlockSize = (UINT32) BlockSize;
1188
1189 //
1190 // Per UEFI Spec, LowestAlignedLba, LogicalBlocksPerPhysicalBlock and OptimalTransferLengthGranularity must be 0
1191 // for logical partitions.
1192 //
1193 if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {
1194 Private->Media.LowestAlignedLba = 0;
1195 Private->Media.LogicalBlocksPerPhysicalBlock = 0;
1196 Private->Media2.LowestAlignedLba = 0;
1197 Private->Media2.LogicalBlocksPerPhysicalBlock = 0;
1198 if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION3) {
1199 Private->Media.OptimalTransferLengthGranularity = 0;
1200 Private->Media2.OptimalTransferLengthGranularity = 0;
1201 }
1202 }
1203
1204 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);
1205
1206 if (Private->DevicePath == NULL) {
1207 FreePool (Private);
1208 return EFI_OUT_OF_RESOURCES;
1209 }
1210
1211 //
1212 // Set the PartitionInfo into Private Data.
1213 //
1214 CopyMem (&Private->PartitionInfo, PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
1215
1216 if ((PartitionInfo->System == 1)) {
1217 Private->EspGuid = &gEfiPartTypeSystemPartGuid;
1218 } else {
1219 //
1220 // If NULL InstallMultipleProtocolInterfaces will ignore it.
1221 //
1222 Private->EspGuid = NULL;
1223 }
1224
1225 //
1226 // Create the new handle.
1227 //
1228 Private->Handle = NULL;
1229 if (Private->DiskIo2 != NULL) {
1230 Status = gBS->InstallMultipleProtocolInterfaces (
1231 &Private->Handle,
1232 &gEfiDevicePathProtocolGuid,
1233 Private->DevicePath,
1234 &gEfiBlockIoProtocolGuid,
1235 &Private->BlockIo,
1236 &gEfiBlockIo2ProtocolGuid,
1237 &Private->BlockIo2,
1238 &gEfiPartitionInfoProtocolGuid,
1239 &Private->PartitionInfo,
1240 Private->EspGuid,
1241 NULL,
1242 NULL
1243 );
1244 } else {
1245 Status = gBS->InstallMultipleProtocolInterfaces (
1246 &Private->Handle,
1247 &gEfiDevicePathProtocolGuid,
1248 Private->DevicePath,
1249 &gEfiBlockIoProtocolGuid,
1250 &Private->BlockIo,
1251 &gEfiPartitionInfoProtocolGuid,
1252 &Private->PartitionInfo,
1253 Private->EspGuid,
1254 NULL,
1255 NULL
1256 );
1257 }
1258
1259 if (!EFI_ERROR (Status)) {
1260 //
1261 // Open the Parent Handle for the child
1262 //
1263 Status = gBS->OpenProtocol (
1264 ParentHandle,
1265 &gEfiDiskIoProtocolGuid,
1266 (VOID **) &ParentDiskIo,
1267 This->DriverBindingHandle,
1268 Private->Handle,
1269 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1270 );
1271 } else {
1272 FreePool (Private->DevicePath);
1273 FreePool (Private);
1274 }
1275
1276 return Status;
1277 }
1278
1279
1280 /**
1281 The user Entry Point for module Partition. The user code starts with this function.
1282
1283 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1284 @param[in] SystemTable A pointer to the EFI System Table.
1285
1286 @retval EFI_SUCCESS The entry point is executed successfully.
1287 @retval other Some error occurs when executing this entry point.
1288
1289 **/
1290 EFI_STATUS
1291 EFIAPI
1292 InitializePartition (
1293 IN EFI_HANDLE ImageHandle,
1294 IN EFI_SYSTEM_TABLE *SystemTable
1295 )
1296 {
1297 EFI_STATUS Status;
1298
1299 //
1300 // Install driver model protocol(s).
1301 //
1302 Status = EfiLibInstallDriverBindingComponentName2 (
1303 ImageHandle,
1304 SystemTable,
1305 &gPartitionDriverBinding,
1306 ImageHandle,
1307 &gPartitionComponentName,
1308 &gPartitionComponentName2
1309 );
1310 ASSERT_EFI_ERROR (Status);
1311
1312
1313 return Status;
1314 }
1315
1316
1317 /**
1318 Test to see if there is any child on ControllerHandle.
1319
1320 @param[in] ControllerHandle Handle of device to test.
1321
1322 @retval TRUE There are children on the ControllerHandle.
1323 @retval FALSE No child is on the ControllerHandle.
1324
1325 **/
1326 BOOLEAN
1327 HasChildren (
1328 IN EFI_HANDLE ControllerHandle
1329 )
1330 {
1331 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
1332 UINTN EntryCount;
1333 EFI_STATUS Status;
1334 UINTN Index;
1335
1336 Status = gBS->OpenProtocolInformation (
1337 ControllerHandle,
1338 &gEfiDiskIoProtocolGuid,
1339 &OpenInfoBuffer,
1340 &EntryCount
1341 );
1342 ASSERT_EFI_ERROR (Status);
1343
1344 for (Index = 0; Index < EntryCount; Index++) {
1345 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
1346 break;
1347 }
1348 }
1349 FreePool (OpenInfoBuffer);
1350
1351 return (BOOLEAN) (Index < EntryCount);
1352 }
1353