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