]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
IntelSiliconPkg: Clean up source files
[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 This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17 **/
18
19
20 #include "Partition.h"
21
22 //
23 // Partition Driver Global Variables.
24 //
25 EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {
26 PartitionDriverBindingSupported,
27 PartitionDriverBindingStart,
28 PartitionDriverBindingStop,
29 //
30 // Grub4Dos copies the BPB of the first partition to the MBR. If the
31 // DriverBindingStart() of the Fat driver gets run before that of Partition
32 // driver only the first partition can be recognized.
33 // Let the driver binding version of Partition driver be higher than that of
34 // Fat driver to make sure the DriverBindingStart() of the Partition driver
35 // gets run before that of Fat driver so that all the partitions can be recognized.
36 //
37 0xb,
38 NULL,
39 NULL
40 };
41
42 //
43 // Prioritized function list to detect partition table.
44 //
45 PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
46 PartitionInstallGptChildHandles,
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 legacy MBR partition types, and then UDF and El Torito.
310 // If the media supports a given partition type install child handles to
311 // 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 EFI_GUID *TypeGuid;
406
407 BlockIo = NULL;
408 BlockIo2 = NULL;
409 Private = NULL;
410
411 if (NumberOfChildren == 0) {
412 //
413 // In the case of re-entry of the PartitionDriverBindingStop, the
414 // NumberOfChildren may not reflect the actual number of children on the
415 // bus driver. Hence, additional check is needed here.
416 //
417 if (HasChildren (ControllerHandle)) {
418 DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: Still has child.\n"));
419 return EFI_DEVICE_ERROR;
420 }
421
422 //
423 // Close the bus driver
424 //
425 gBS->CloseProtocol (
426 ControllerHandle,
427 &gEfiDiskIoProtocolGuid,
428 This->DriverBindingHandle,
429 ControllerHandle
430 );
431 //
432 // Close Parent BlockIO2 if has.
433 //
434 gBS->CloseProtocol (
435 ControllerHandle,
436 &gEfiDiskIo2ProtocolGuid,
437 This->DriverBindingHandle,
438 ControllerHandle
439 );
440
441 gBS->CloseProtocol (
442 ControllerHandle,
443 &gEfiDevicePathProtocolGuid,
444 This->DriverBindingHandle,
445 ControllerHandle
446 );
447 return EFI_SUCCESS;
448 }
449
450 AllChildrenStopped = TRUE;
451 for (Index = 0; Index < NumberOfChildren; Index++) {
452 gBS->OpenProtocol (
453 ChildHandleBuffer[Index],
454 &gEfiBlockIoProtocolGuid,
455 (VOID **) &BlockIo,
456 This->DriverBindingHandle,
457 ControllerHandle,
458 EFI_OPEN_PROTOCOL_GET_PROTOCOL
459 );
460 //
461 // Try to locate BlockIo2.
462 //
463 gBS->OpenProtocol (
464 ChildHandleBuffer[Index],
465 &gEfiBlockIo2ProtocolGuid,
466 (VOID **) &BlockIo2,
467 This->DriverBindingHandle,
468 ControllerHandle,
469 EFI_OPEN_PROTOCOL_GET_PROTOCOL
470 );
471
472
473 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
474 if (Private->InStop) {
475 //
476 // If the child handle is going to be stopped again during the re-entry
477 // of DriverBindingStop, just do nothing.
478 //
479 break;
480 }
481 Private->InStop = TRUE;
482
483 BlockIo->FlushBlocks (BlockIo);
484
485 if (BlockIo2 != NULL) {
486 Status = BlockIo2->FlushBlocksEx (BlockIo2, NULL);
487 DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: FlushBlocksEx returned with %r\n", Status));
488 } else {
489 Status = EFI_SUCCESS;
490 }
491
492 gBS->CloseProtocol (
493 ControllerHandle,
494 &gEfiDiskIoProtocolGuid,
495 This->DriverBindingHandle,
496 ChildHandleBuffer[Index]
497 );
498
499 if (IsZeroGuid (&Private->TypeGuid)) {
500 TypeGuid = NULL;
501 } else {
502 TypeGuid = &Private->TypeGuid;
503 }
504
505 //
506 // All Software protocols have be freed from the handle so remove it.
507 // Remove the BlockIo Protocol if has.
508 // Remove the BlockIo2 Protocol if has.
509 //
510 if (BlockIo2 != NULL) {
511 //
512 // Some device drivers might re-install the BlockIO(2) protocols for a
513 // media change condition. Therefore, if the FlushBlocksEx returned with
514 // EFI_MEDIA_CHANGED, just let the BindingStop fail to avoid potential
515 // reference of already stopped child handle.
516 //
517 if (Status != EFI_MEDIA_CHANGED) {
518 Status = gBS->UninstallMultipleProtocolInterfaces (
519 ChildHandleBuffer[Index],
520 &gEfiDevicePathProtocolGuid,
521 Private->DevicePath,
522 &gEfiBlockIoProtocolGuid,
523 &Private->BlockIo,
524 &gEfiBlockIo2ProtocolGuid,
525 &Private->BlockIo2,
526 &gEfiPartitionInfoProtocolGuid,
527 &Private->PartitionInfo,
528 TypeGuid,
529 NULL,
530 NULL
531 );
532 }
533 } else {
534 Status = gBS->UninstallMultipleProtocolInterfaces (
535 ChildHandleBuffer[Index],
536 &gEfiDevicePathProtocolGuid,
537 Private->DevicePath,
538 &gEfiBlockIoProtocolGuid,
539 &Private->BlockIo,
540 &gEfiPartitionInfoProtocolGuid,
541 &Private->PartitionInfo,
542 TypeGuid,
543 NULL,
544 NULL
545 );
546 }
547
548 if (EFI_ERROR (Status)) {
549 Private->InStop = FALSE;
550 gBS->OpenProtocol (
551 ControllerHandle,
552 &gEfiDiskIoProtocolGuid,
553 (VOID **) &DiskIo,
554 This->DriverBindingHandle,
555 ChildHandleBuffer[Index],
556 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
557 );
558 } else {
559 FreePool (Private->DevicePath);
560 FreePool (Private);
561 }
562
563 if (EFI_ERROR (Status)) {
564 AllChildrenStopped = FALSE;
565 if (Status == EFI_MEDIA_CHANGED) {
566 break;
567 }
568 }
569 }
570
571 if (!AllChildrenStopped) {
572 return EFI_DEVICE_ERROR;
573 }
574
575 return EFI_SUCCESS;
576 }
577
578
579 /**
580 Reset the Block Device.
581
582 @param This Protocol instance pointer.
583 @param ExtendedVerification Driver may perform diagnostics on reset.
584
585 @retval EFI_SUCCESS The device was reset.
586 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
587 not be reset.
588
589 **/
590 EFI_STATUS
591 EFIAPI
592 PartitionReset (
593 IN EFI_BLOCK_IO_PROTOCOL *This,
594 IN BOOLEAN ExtendedVerification
595 )
596 {
597 PARTITION_PRIVATE_DATA *Private;
598
599 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
600
601 return Private->ParentBlockIo->Reset (
602 Private->ParentBlockIo,
603 ExtendedVerification
604 );
605 }
606
607 /**
608 Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
609 for no media or media change case. Otherwise DefaultStatus is returned.
610
611 @param DiskIo Pointer to the DiskIo instance.
612 @param MediaId Id of the media, changes every time the media is replaced.
613 @param DefaultStatus The default status to return when it's not the no media
614 or media change case.
615
616 @retval EFI_NO_MEDIA There is no media.
617 @retval EFI_MEDIA_CHANGED The media was changed.
618 @retval others The default status to return.
619 **/
620 EFI_STATUS
621 ProbeMediaStatus (
622 IN EFI_DISK_IO_PROTOCOL *DiskIo,
623 IN UINT32 MediaId,
624 IN EFI_STATUS DefaultStatus
625 )
626 {
627 EFI_STATUS Status;
628 UINT8 Buffer[1];
629
630 //
631 // Read 1 byte from offset 0 to check if the MediaId is still valid.
632 // The reading operation is synchronious thus it is not worth it to
633 // allocate a buffer from the pool. The destination buffer for the
634 // data is in the stack.
635 //
636 Status = DiskIo->ReadDisk (DiskIo, MediaId, 0, 1, (VOID*)Buffer);
637 if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
638 return Status;
639 }
640 return DefaultStatus;
641 }
642
643 /**
644 Read by using the Disk IO protocol on the parent device. Lba addresses
645 must be converted to byte offsets.
646
647 @param This Protocol instance pointer.
648 @param MediaId Id of the media, changes every time the media is replaced.
649 @param Lba The starting Logical Block Address to read from
650 @param BufferSize Size of Buffer, must be a multiple of device block size.
651 @param Buffer Buffer containing read data
652
653 @retval EFI_SUCCESS The data was read correctly from the device.
654 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
655 @retval EFI_NO_MEDIA There is no media in the device.
656 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
657 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
658 @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
659 valid for the device.
660
661 **/
662 EFI_STATUS
663 EFIAPI
664 PartitionReadBlocks (
665 IN EFI_BLOCK_IO_PROTOCOL *This,
666 IN UINT32 MediaId,
667 IN EFI_LBA Lba,
668 IN UINTN BufferSize,
669 OUT VOID *Buffer
670 )
671 {
672 PARTITION_PRIVATE_DATA *Private;
673 UINT64 Offset;
674
675 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
676
677 if (BufferSize % Private->BlockSize != 0) {
678 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
679 }
680
681 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
682 if (Offset + BufferSize > Private->End) {
683 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
684 }
685 //
686 // Because some kinds of partition have different block size from their parent
687 // device, we call the Disk IO protocol on the parent device, not the Block IO
688 // protocol
689 //
690 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
691 }
692
693 /**
694 Write by using the Disk IO protocol on the parent device. Lba addresses
695 must be converted to byte offsets.
696
697 @param[in] This Protocol instance pointer.
698 @param[in] MediaId Id of the media, changes every time the media is replaced.
699 @param[in] Lba The starting Logical Block Address to read from
700 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
701 @param[in] Buffer Buffer containing data to be written to device.
702
703 @retval EFI_SUCCESS The data was written correctly to the device.
704 @retval EFI_WRITE_PROTECTED The device can not be written to.
705 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
706 @retval EFI_NO_MEDIA There is no media in the device.
707 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
708 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
709 @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not
710 valid for the device.
711
712 **/
713 EFI_STATUS
714 EFIAPI
715 PartitionWriteBlocks (
716 IN EFI_BLOCK_IO_PROTOCOL *This,
717 IN UINT32 MediaId,
718 IN EFI_LBA Lba,
719 IN UINTN BufferSize,
720 IN VOID *Buffer
721 )
722 {
723 PARTITION_PRIVATE_DATA *Private;
724 UINT64 Offset;
725
726 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
727
728 if (BufferSize % Private->BlockSize != 0) {
729 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
730 }
731
732 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
733 if (Offset + BufferSize > Private->End) {
734 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
735 }
736 //
737 // Because some kinds of partition have different block size from their parent
738 // device, we call the Disk IO protocol on the parent device, not the Block IO
739 // protocol
740 //
741 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
742 }
743
744
745 /**
746 Flush the parent Block Device.
747
748 @param This Protocol instance pointer.
749
750 @retval EFI_SUCCESS All outstanding data was written to the device
751 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
752 @retval EFI_NO_MEDIA There is no media in the device.
753
754 **/
755 EFI_STATUS
756 EFIAPI
757 PartitionFlushBlocks (
758 IN EFI_BLOCK_IO_PROTOCOL *This
759 )
760 {
761 PARTITION_PRIVATE_DATA *Private;
762
763 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
764
765 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
766 }
767
768 /**
769 Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
770 for no media or media change case. Otherwise DefaultStatus is returned.
771
772 @param DiskIo2 Pointer to the DiskIo2 instance.
773 @param MediaId Id of the media, changes every time the media is replaced.
774 @param DefaultStatus The default status to return when it's not the no media
775 or media change case.
776
777 @retval EFI_NO_MEDIA There is no media.
778 @retval EFI_MEDIA_CHANGED The media was changed.
779 @retval others The default status to return.
780 **/
781 EFI_STATUS
782 ProbeMediaStatusEx (
783 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
784 IN UINT32 MediaId,
785 IN EFI_STATUS DefaultStatus
786 )
787 {
788 EFI_STATUS Status;
789 UINT8 Buffer[1];
790
791 //
792 // Read 1 byte from offset 0 to check if the MediaId is still valid.
793 // The reading operation is synchronious thus it is not worth it to
794 // allocate a buffer from the pool. The destination buffer for the
795 // data is in the stack.
796 //
797 Status = DiskIo2->ReadDiskEx (DiskIo2, MediaId, 0, NULL, 1, (VOID*)Buffer);
798 if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
799 return Status;
800 }
801 return DefaultStatus;
802 }
803
804 /**
805 Reset the Block Device throught Block I/O2 protocol.
806
807 @param This Protocol instance pointer.
808 @param ExtendedVerification Driver may perform diagnostics on reset.
809
810 @retval EFI_SUCCESS The device was reset.
811 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
812 not be reset.
813
814 **/
815 EFI_STATUS
816 EFIAPI
817 PartitionResetEx (
818 IN EFI_BLOCK_IO2_PROTOCOL *This,
819 IN BOOLEAN ExtendedVerification
820 )
821 {
822 PARTITION_PRIVATE_DATA *Private;
823
824 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
825
826 return Private->ParentBlockIo2->Reset (
827 Private->ParentBlockIo2,
828 ExtendedVerification
829 );
830 }
831
832 /**
833 The general callback for the DiskIo2 interfaces.
834 @param Event Event whose notification function is being invoked.
835 @param Context The pointer to the notification function's context,
836 which points to the PARTITION_ACCESS_TASK instance.
837 **/
838 VOID
839 EFIAPI
840 PartitionOnAccessComplete (
841 IN EFI_EVENT Event,
842 IN VOID *Context
843 )
844 {
845 PARTITION_ACCESS_TASK *Task;
846
847 Task = (PARTITION_ACCESS_TASK *) Context;
848
849 gBS->CloseEvent (Event);
850
851 Task->BlockIo2Token->TransactionStatus = Task->DiskIo2Token.TransactionStatus;
852 gBS->SignalEvent (Task->BlockIo2Token->Event);
853
854 FreePool (Task);
855 }
856
857 /**
858 Create a new PARTITION_ACCESS_TASK instance.
859
860 @param Token Pointer to the EFI_BLOCK_IO2_TOKEN.
861
862 @return Pointer to the created PARTITION_ACCESS_TASK instance or NULL upon failure.
863 **/
864 PARTITION_ACCESS_TASK *
865 PartitionCreateAccessTask (
866 IN EFI_BLOCK_IO2_TOKEN *Token
867 )
868 {
869 EFI_STATUS Status;
870 PARTITION_ACCESS_TASK *Task;
871
872 Task = AllocatePool (sizeof (*Task));
873 if (Task == NULL) {
874 return NULL;
875 }
876
877 Status = gBS->CreateEvent (
878 EVT_NOTIFY_SIGNAL,
879 TPL_NOTIFY,
880 PartitionOnAccessComplete,
881 Task,
882 &Task->DiskIo2Token.Event
883 );
884 if (EFI_ERROR (Status)) {
885 FreePool (Task);
886 return NULL;
887 }
888
889 Task->BlockIo2Token = Token;
890
891 return Task;
892 }
893
894 /**
895 Read BufferSize bytes from Lba into Buffer.
896
897 This function reads the requested number of blocks from the device. All the
898 blocks are read, or an error is returned.
899 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
900 non-blocking I/O is being used, the Event associated with this request will
901 not be signaled.
902
903 @param[in] This Indicates a pointer to the calling context.
904 @param[in] MediaId Id of the media, changes every time the media is
905 replaced.
906 @param[in] Lba The starting Logical Block Address to read from.
907 @param[in, out] Token A pointer to the token associated with the transaction.
908 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
909 @param[out] Buffer A pointer to the destination buffer for the data. The
910 caller is responsible for either having implicit or
911 explicit ownership of the buffer.
912
913 @retval EFI_SUCCESS The read request was queued if Token->Event is
914 not NULL.The data was read correctly from the
915 device if the Token->Event is NULL.
916 @retval EFI_DEVICE_ERROR The device reported an error while performing
917 the read.
918 @retval EFI_NO_MEDIA There is no media in the device.
919 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
920 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
921 intrinsic block size of the device.
922 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
923 or the buffer is not on proper alignment.
924 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
925 of resources.
926 **/
927 EFI_STATUS
928 EFIAPI
929 PartitionReadBlocksEx (
930 IN EFI_BLOCK_IO2_PROTOCOL *This,
931 IN UINT32 MediaId,
932 IN EFI_LBA Lba,
933 IN OUT EFI_BLOCK_IO2_TOKEN *Token,
934 IN UINTN BufferSize,
935 OUT VOID *Buffer
936 )
937 {
938 EFI_STATUS Status;
939 PARTITION_PRIVATE_DATA *Private;
940 UINT64 Offset;
941 PARTITION_ACCESS_TASK *Task;
942
943 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
944
945 if (BufferSize % Private->BlockSize != 0) {
946 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
947 }
948
949 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
950 if (Offset + BufferSize > Private->End) {
951 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
952 }
953
954 if ((Token != NULL) && (Token->Event != NULL)) {
955 Task = PartitionCreateAccessTask (Token);
956 if (Task == NULL) {
957 return EFI_OUT_OF_RESOURCES;
958 }
959
960 Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
961 if (EFI_ERROR (Status)) {
962 gBS->CloseEvent (Task->DiskIo2Token.Event);
963 FreePool (Task);
964 }
965 } else {
966 Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
967 }
968
969 return Status;
970 }
971
972 /**
973 Write BufferSize bytes from Lba into Buffer.
974
975 This function writes the requested number of blocks to the device. All blocks
976 are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
977 EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
978 being used, the Event associated with this request will not be signaled.
979
980 @param[in] This Indicates a pointer to the calling context.
981 @param[in] MediaId The media ID that the write request is for.
982 @param[in] Lba The starting logical block address to be written. The
983 caller is responsible for writing to only legitimate
984 locations.
985 @param[in, out] Token A pointer to the token associated with the transaction.
986 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
987 @param[in] Buffer A pointer to the source buffer for the data.
988
989 @retval EFI_SUCCESS The write request was queued if Event is not NULL.
990 The data was written correctly to the device if
991 the Event is NULL.
992 @retval EFI_WRITE_PROTECTED The device can not be written to.
993 @retval EFI_NO_MEDIA There is no media in the device.
994 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
995 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
996 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
997 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
998 or the buffer is not on proper alignment.
999 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1000 of resources.
1001
1002 **/
1003 EFI_STATUS
1004 EFIAPI
1005 PartitionWriteBlocksEx (
1006 IN EFI_BLOCK_IO2_PROTOCOL *This,
1007 IN UINT32 MediaId,
1008 IN EFI_LBA Lba,
1009 IN OUT EFI_BLOCK_IO2_TOKEN *Token,
1010 IN UINTN BufferSize,
1011 IN VOID *Buffer
1012 )
1013 {
1014 EFI_STATUS Status;
1015 PARTITION_PRIVATE_DATA *Private;
1016 UINT64 Offset;
1017 PARTITION_ACCESS_TASK *Task;
1018
1019 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
1020
1021 if (BufferSize % Private->BlockSize != 0) {
1022 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
1023 }
1024
1025 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
1026 if (Offset + BufferSize > Private->End) {
1027 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
1028 }
1029
1030 if ((Token != NULL) && (Token->Event != NULL)) {
1031 Task = PartitionCreateAccessTask (Token);
1032 if (Task == NULL) {
1033 return EFI_OUT_OF_RESOURCES;
1034 }
1035
1036 Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
1037 if (EFI_ERROR (Status)) {
1038 gBS->CloseEvent (Task->DiskIo2Token.Event);
1039 FreePool (Task);
1040 }
1041 } else {
1042 Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
1043 }
1044 return Status;
1045 }
1046
1047 /**
1048 Flush the Block Device.
1049
1050 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
1051 is returned and non-blocking I/O is being used, the Event associated with
1052 this request will not be signaled.
1053
1054 @param[in] This Indicates a pointer to the calling context.
1055 @param[in, out] Token A pointer to the token associated with the transaction
1056
1057 @retval EFI_SUCCESS The flush request was queued if Event is not NULL.
1058 All outstanding data was written correctly to the
1059 device if the Event is NULL.
1060 @retval EFI_DEVICE_ERROR The device reported an error while writting back
1061 the data.
1062 @retval EFI_WRITE_PROTECTED The device cannot be written to.
1063 @retval EFI_NO_MEDIA There is no media in the device.
1064 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1065 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1066 of resources.
1067
1068 **/
1069 EFI_STATUS
1070 EFIAPI
1071 PartitionFlushBlocksEx (
1072 IN EFI_BLOCK_IO2_PROTOCOL *This,
1073 IN OUT EFI_BLOCK_IO2_TOKEN *Token
1074 )
1075 {
1076 EFI_STATUS Status;
1077 PARTITION_PRIVATE_DATA *Private;
1078 PARTITION_ACCESS_TASK *Task;
1079
1080 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
1081
1082 if ((Token != NULL) && (Token->Event != NULL)) {
1083 Task = PartitionCreateAccessTask (Token);
1084 if (Task == NULL) {
1085 return EFI_OUT_OF_RESOURCES;
1086 }
1087
1088 Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, &Task->DiskIo2Token);
1089 if (EFI_ERROR (Status)) {
1090 gBS->CloseEvent (Task->DiskIo2Token.Event);
1091 FreePool (Task);
1092 }
1093 } else {
1094 Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, NULL);
1095 }
1096 return Status;
1097 }
1098
1099
1100 /**
1101 Create a child handle for a logical block device that represents the
1102 bytes Start to End of the Parent Block IO device.
1103
1104 @param[in] This Protocol instance pointer.
1105 @param[in] ParentHandle Parent Handle for new child.
1106 @param[in] ParentDiskIo Parent DiskIo interface.
1107 @param[in] ParentDiskIo2 Parent DiskIo2 interface.
1108 @param[in] ParentBlockIo Parent BlockIo interface.
1109 @param[in] ParentBlockIo2 Parent BlockIo2 interface.
1110 @param[in] ParentDevicePath Parent Device Path.
1111 @param[in] DevicePathNode Child Device Path node.
1112 @param[in] PartitionInfo Child Partition Information interface.
1113 @param[in] Start Start Block.
1114 @param[in] End End Block.
1115 @param[in] BlockSize Child block size.
1116 @param[in] TypeGuid Partition GUID Type.
1117
1118 @retval EFI_SUCCESS A child handle was added.
1119 @retval other A child handle was not added.
1120
1121 **/
1122 EFI_STATUS
1123 PartitionInstallChildHandle (
1124 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1125 IN EFI_HANDLE ParentHandle,
1126 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
1127 IN EFI_DISK_IO2_PROTOCOL *ParentDiskIo2,
1128 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
1129 IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2,
1130 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
1131 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
1132 IN EFI_PARTITION_INFO_PROTOCOL *PartitionInfo,
1133 IN EFI_LBA Start,
1134 IN EFI_LBA End,
1135 IN UINT32 BlockSize,
1136 IN EFI_GUID *TypeGuid
1137 )
1138 {
1139 EFI_STATUS Status;
1140 PARTITION_PRIVATE_DATA *Private;
1141
1142 Status = EFI_SUCCESS;
1143 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));
1144 if (Private == NULL) {
1145 return EFI_OUT_OF_RESOURCES;
1146 }
1147
1148 Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;
1149
1150 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);
1151 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);
1152
1153 Private->BlockSize = BlockSize;
1154 Private->ParentBlockIo = ParentBlockIo;
1155 Private->ParentBlockIo2 = ParentBlockIo2;
1156 Private->DiskIo = ParentDiskIo;
1157 Private->DiskIo2 = ParentDiskIo2;
1158
1159 //
1160 // Set the BlockIO into Private Data.
1161 //
1162 Private->BlockIo.Revision = ParentBlockIo->Revision;
1163
1164 Private->BlockIo.Media = &Private->Media;
1165 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
1166
1167 Private->BlockIo.Reset = PartitionReset;
1168 Private->BlockIo.ReadBlocks = PartitionReadBlocks;
1169 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;
1170 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;
1171
1172 //
1173 // Set the BlockIO2 into Private Data.
1174 //
1175 if (Private->DiskIo2 != NULL) {
1176 ASSERT (Private->ParentBlockIo2 != NULL);
1177 Private->BlockIo2.Media = &Private->Media2;
1178 CopyMem (Private->BlockIo2.Media, ParentBlockIo2->Media, sizeof (EFI_BLOCK_IO_MEDIA));
1179
1180 Private->BlockIo2.Reset = PartitionResetEx;
1181 Private->BlockIo2.ReadBlocksEx = PartitionReadBlocksEx;
1182 Private->BlockIo2.WriteBlocksEx = PartitionWriteBlocksEx;
1183 Private->BlockIo2.FlushBlocksEx = PartitionFlushBlocksEx;
1184 }
1185
1186 Private->Media.IoAlign = 0;
1187 Private->Media.LogicalPartition = TRUE;
1188 Private->Media.LastBlock = DivU64x32 (
1189 MultU64x32 (
1190 End - Start + 1,
1191 ParentBlockIo->Media->BlockSize
1192 ),
1193 BlockSize
1194 ) - 1;
1195
1196 Private->Media.BlockSize = (UINT32) BlockSize;
1197
1198 Private->Media2.IoAlign = 0;
1199 Private->Media2.LogicalPartition = TRUE;
1200 Private->Media2.LastBlock = Private->Media.LastBlock;
1201 Private->Media2.BlockSize = (UINT32) BlockSize;
1202
1203 //
1204 // Per UEFI Spec, LowestAlignedLba, LogicalBlocksPerPhysicalBlock and OptimalTransferLengthGranularity must be 0
1205 // for logical partitions.
1206 //
1207 if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {
1208 Private->Media.LowestAlignedLba = 0;
1209 Private->Media.LogicalBlocksPerPhysicalBlock = 0;
1210 Private->Media2.LowestAlignedLba = 0;
1211 Private->Media2.LogicalBlocksPerPhysicalBlock = 0;
1212 if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION3) {
1213 Private->Media.OptimalTransferLengthGranularity = 0;
1214 Private->Media2.OptimalTransferLengthGranularity = 0;
1215 }
1216 }
1217
1218 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);
1219
1220 if (Private->DevicePath == NULL) {
1221 FreePool (Private);
1222 return EFI_OUT_OF_RESOURCES;
1223 }
1224
1225 //
1226 // Set the PartitionInfo into Private Data.
1227 //
1228 CopyMem (&Private->PartitionInfo, PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
1229
1230 if (TypeGuid != NULL) {
1231 CopyGuid(&(Private->TypeGuid), TypeGuid);
1232 } else {
1233 ZeroMem ((VOID *)&(Private->TypeGuid), sizeof (EFI_GUID));
1234 }
1235
1236 //
1237 // Create the new handle.
1238 //
1239 Private->Handle = NULL;
1240 if (Private->DiskIo2 != NULL) {
1241 Status = gBS->InstallMultipleProtocolInterfaces (
1242 &Private->Handle,
1243 &gEfiDevicePathProtocolGuid,
1244 Private->DevicePath,
1245 &gEfiBlockIoProtocolGuid,
1246 &Private->BlockIo,
1247 &gEfiBlockIo2ProtocolGuid,
1248 &Private->BlockIo2,
1249 &gEfiPartitionInfoProtocolGuid,
1250 &Private->PartitionInfo,
1251 TypeGuid,
1252 NULL,
1253 NULL
1254 );
1255 } else {
1256 Status = gBS->InstallMultipleProtocolInterfaces (
1257 &Private->Handle,
1258 &gEfiDevicePathProtocolGuid,
1259 Private->DevicePath,
1260 &gEfiBlockIoProtocolGuid,
1261 &Private->BlockIo,
1262 &gEfiPartitionInfoProtocolGuid,
1263 &Private->PartitionInfo,
1264 TypeGuid,
1265 NULL,
1266 NULL
1267 );
1268 }
1269
1270 if (!EFI_ERROR (Status)) {
1271 //
1272 // Open the Parent Handle for the child
1273 //
1274 Status = gBS->OpenProtocol (
1275 ParentHandle,
1276 &gEfiDiskIoProtocolGuid,
1277 (VOID **) &ParentDiskIo,
1278 This->DriverBindingHandle,
1279 Private->Handle,
1280 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1281 );
1282 } else {
1283 FreePool (Private->DevicePath);
1284 FreePool (Private);
1285 }
1286
1287 return Status;
1288 }
1289
1290
1291 /**
1292 The user Entry Point for module Partition. The user code starts with this function.
1293
1294 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1295 @param[in] SystemTable A pointer to the EFI System Table.
1296
1297 @retval EFI_SUCCESS The entry point is executed successfully.
1298 @retval other Some error occurs when executing this entry point.
1299
1300 **/
1301 EFI_STATUS
1302 EFIAPI
1303 InitializePartition (
1304 IN EFI_HANDLE ImageHandle,
1305 IN EFI_SYSTEM_TABLE *SystemTable
1306 )
1307 {
1308 EFI_STATUS Status;
1309
1310 //
1311 // Install driver model protocol(s).
1312 //
1313 Status = EfiLibInstallDriverBindingComponentName2 (
1314 ImageHandle,
1315 SystemTable,
1316 &gPartitionDriverBinding,
1317 ImageHandle,
1318 &gPartitionComponentName,
1319 &gPartitionComponentName2
1320 );
1321 ASSERT_EFI_ERROR (Status);
1322
1323
1324 return Status;
1325 }
1326
1327
1328 /**
1329 Test to see if there is any child on ControllerHandle.
1330
1331 @param[in] ControllerHandle Handle of device to test.
1332
1333 @retval TRUE There are children on the ControllerHandle.
1334 @retval FALSE No child is on the ControllerHandle.
1335
1336 **/
1337 BOOLEAN
1338 HasChildren (
1339 IN EFI_HANDLE ControllerHandle
1340 )
1341 {
1342 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
1343 UINTN EntryCount;
1344 EFI_STATUS Status;
1345 UINTN Index;
1346
1347 Status = gBS->OpenProtocolInformation (
1348 ControllerHandle,
1349 &gEfiDiskIoProtocolGuid,
1350 &OpenInfoBuffer,
1351 &EntryCount
1352 );
1353 ASSERT_EFI_ERROR (Status);
1354
1355 for (Index = 0; Index < EntryCount; Index++) {
1356 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
1357 break;
1358 }
1359 }
1360 FreePool (OpenInfoBuffer);
1361
1362 return (BOOLEAN) (Index < EntryCount);
1363 }
1364