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