OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
Partition.c
Go to the documentation of this file.
1
13#include "Partition.h"
14
15//
16// Partition Driver Global Variables.
17//
18EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {
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//
53
69EFI_STATUS
70EFIAPI
72 IN EFI_DRIVER_BINDING_PROTOCOL *This,
73 IN EFI_HANDLE ControllerHandle,
74 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
75 )
76{
77 EFI_STATUS Status;
78 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
79 EFI_DISK_IO_PROTOCOL *DiskIo;
80 EFI_DEV_PATH *Node;
81
82 //
83 // Check RemainingDevicePath validation
84 //
85 if (RemainingDevicePath != NULL) {
86 //
87 // Check if RemainingDevicePath is the End of Device Path Node,
88 // if yes, go on checking other conditions
89 //
90 if (!IsDevicePathEnd (RemainingDevicePath)) {
91 //
92 // If RemainingDevicePath isn't the End of Device Path Node,
93 // check its validation
94 //
95 Node = (EFI_DEV_PATH *)RemainingDevicePath;
96 if ((Node->DevPath.Type != MEDIA_DEVICE_PATH) ||
97 (Node->DevPath.SubType != MEDIA_HARDDRIVE_DP) ||
98 (DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)))
99 {
100 return EFI_UNSUPPORTED;
101 }
102 }
103 }
104
105 //
106 // Open the IO Abstraction(s) needed to perform the supported test
107 //
108 Status = gBS->OpenProtocol (
109 ControllerHandle,
111 (VOID **)&DiskIo,
112 This->DriverBindingHandle,
113 ControllerHandle,
114 EFI_OPEN_PROTOCOL_BY_DRIVER
115 );
116 if (Status == EFI_ALREADY_STARTED) {
117 return EFI_SUCCESS;
118 }
119
120 if (EFI_ERROR (Status)) {
121 return Status;
122 }
123
124 //
125 // Close the I/O Abstraction(s) used to perform the supported test
126 //
127 gBS->CloseProtocol (
128 ControllerHandle,
130 This->DriverBindingHandle,
131 ControllerHandle
132 );
133
134 //
135 // Open the EFI Device Path protocol needed to perform the supported test
136 //
137 Status = gBS->OpenProtocol (
138 ControllerHandle,
140 (VOID **)&ParentDevicePath,
141 This->DriverBindingHandle,
142 ControllerHandle,
143 EFI_OPEN_PROTOCOL_BY_DRIVER
144 );
145 if (Status == EFI_ALREADY_STARTED) {
146 return EFI_SUCCESS;
147 }
148
149 if (EFI_ERROR (Status)) {
150 return Status;
151 }
152
153 //
154 // Close protocol, don't use device path protocol in the Support() function
155 //
156 gBS->CloseProtocol (
157 ControllerHandle,
159 This->DriverBindingHandle,
160 ControllerHandle
161 );
162
163 //
164 // Open the IO Abstraction(s) needed to perform the supported test
165 //
166 Status = gBS->OpenProtocol (
167 ControllerHandle,
169 NULL,
170 This->DriverBindingHandle,
171 ControllerHandle,
172 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
173 );
174
175 return Status;
176}
177
193EFI_STATUS
194EFIAPI
196 IN EFI_DRIVER_BINDING_PROTOCOL *This,
197 IN EFI_HANDLE ControllerHandle,
198 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
199 )
200{
201 EFI_STATUS Status;
202 EFI_STATUS OpenStatus;
203 EFI_BLOCK_IO_PROTOCOL *BlockIo;
204 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
205 EFI_DISK_IO_PROTOCOL *DiskIo;
206 EFI_DISK_IO2_PROTOCOL *DiskIo2;
207 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
209 BOOLEAN MediaPresent;
210 EFI_TPL OldTpl;
211
212 BlockIo2 = NULL;
213 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
214 //
215 // Check RemainingDevicePath validation
216 //
217 if (RemainingDevicePath != NULL) {
218 //
219 // Check if RemainingDevicePath is the End of Device Path Node,
220 // if yes, return EFI_SUCCESS
221 //
222 if (IsDevicePathEnd (RemainingDevicePath)) {
223 Status = EFI_SUCCESS;
224 goto Exit;
225 }
226 }
227
228 //
229 // Try to open BlockIO and BlockIO2. If BlockIO would be opened, continue,
230 // otherwise, return error.
231 //
232 Status = gBS->OpenProtocol (
233 ControllerHandle,
235 (VOID **)&BlockIo,
236 This->DriverBindingHandle,
237 ControllerHandle,
238 EFI_OPEN_PROTOCOL_GET_PROTOCOL
239 );
240 if (EFI_ERROR (Status)) {
241 goto Exit;
242 }
243
244 Status = gBS->OpenProtocol (
245 ControllerHandle,
246 &gEfiBlockIo2ProtocolGuid,
247 (VOID **)&BlockIo2,
248 This->DriverBindingHandle,
249 ControllerHandle,
250 EFI_OPEN_PROTOCOL_GET_PROTOCOL
251 );
252 if (EFI_ERROR (Status)) {
253 BlockIo2 = NULL;
254 }
255
256 //
257 // Get the Device Path Protocol on ControllerHandle's handle.
258 //
259 Status = gBS->OpenProtocol (
260 ControllerHandle,
262 (VOID **)&ParentDevicePath,
263 This->DriverBindingHandle,
264 ControllerHandle,
265 EFI_OPEN_PROTOCOL_BY_DRIVER
266 );
267 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
268 goto Exit;
269 }
270
271 //
272 // Get the DiskIo and DiskIo2.
273 //
274 Status = gBS->OpenProtocol (
275 ControllerHandle,
277 (VOID **)&DiskIo,
278 This->DriverBindingHandle,
279 ControllerHandle,
280 EFI_OPEN_PROTOCOL_BY_DRIVER
281 );
282 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
283 gBS->CloseProtocol (
284 ControllerHandle,
286 This->DriverBindingHandle,
287 ControllerHandle
288 );
289 goto Exit;
290 }
291
292 OpenStatus = Status;
293
294 Status = gBS->OpenProtocol (
295 ControllerHandle,
297 (VOID **)&DiskIo2,
298 This->DriverBindingHandle,
299 ControllerHandle,
300 EFI_OPEN_PROTOCOL_BY_DRIVER
301 );
302 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
303 DiskIo2 = NULL;
304 }
305
306 //
307 // Try to read blocks when there's media or it is removable physical partition.
308 //
309 Status = EFI_UNSUPPORTED;
310 MediaPresent = BlockIo->Media->MediaPresent;
311 if (BlockIo->Media->MediaPresent ||
312 (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition))
313 {
314 //
315 // Try for GPT, then legacy MBR partition types, and then UDF and El Torito.
316 // If the media supports a given partition type install child handles to
317 // represent the partitions described by the media.
318 //
319 Routine = &mPartitionDetectRoutineTable[0];
320 while (*Routine != NULL) {
321 Status = (*Routine)(
322 This,
323 ControllerHandle,
324 DiskIo,
325 DiskIo2,
326 BlockIo,
327 BlockIo2,
328 ParentDevicePath
329 );
330 if (!EFI_ERROR (Status) || (Status == EFI_MEDIA_CHANGED) || (Status == EFI_NO_MEDIA)) {
331 break;
332 }
333
334 Routine++;
335 }
336 }
337
338 //
339 // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),
340 // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the
341 // driver. So don't try to close them. Otherwise, we will break the dependency
342 // between the controller and the driver set up before.
343 //
344 // In the case that when the media changes on a device it will Reinstall the
345 // BlockIo interaface. This will cause a call to our Stop(), and a subsequent
346 // reentrant call to our Start() successfully. We should leave the device open
347 // when this happen. The "media change" case includes either the status is
348 // EFI_MEDIA_CHANGED or it is a "media" to "no media" change.
349 //
350 if (EFI_ERROR (Status) &&
351 !EFI_ERROR (OpenStatus) &&
352 (Status != EFI_MEDIA_CHANGED) &&
353 !(MediaPresent && (Status == EFI_NO_MEDIA)))
354 {
355 gBS->CloseProtocol (
356 ControllerHandle,
358 This->DriverBindingHandle,
359 ControllerHandle
360 );
361 //
362 // Close Parent DiskIo2 if has.
363 //
364 gBS->CloseProtocol (
365 ControllerHandle,
367 This->DriverBindingHandle,
368 ControllerHandle
369 );
370
371 gBS->CloseProtocol (
372 ControllerHandle,
374 This->DriverBindingHandle,
375 ControllerHandle
376 );
377 }
378
379Exit:
380 gBS->RestoreTPL (OldTpl);
381 return Status;
382}
383
398EFI_STATUS
399EFIAPI
401 IN EFI_DRIVER_BINDING_PROTOCOL *This,
402 IN EFI_HANDLE ControllerHandle,
403 IN UINTN NumberOfChildren,
404 IN EFI_HANDLE *ChildHandleBuffer
405 )
406{
407 EFI_STATUS Status;
408 UINTN Index;
409 EFI_BLOCK_IO_PROTOCOL *BlockIo;
410 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
411 BOOLEAN AllChildrenStopped;
412 PARTITION_PRIVATE_DATA *Private;
413 EFI_DISK_IO_PROTOCOL *DiskIo;
414 EFI_GUID *TypeGuid;
415
416 BlockIo = NULL;
417 BlockIo2 = NULL;
418 Private = NULL;
419
420 if (NumberOfChildren == 0) {
421 //
422 // In the case of re-entry of the PartitionDriverBindingStop, the
423 // NumberOfChildren may not reflect the actual number of children on the
424 // bus driver. Hence, additional check is needed here.
425 //
426 if (HasChildren (ControllerHandle)) {
427 DEBUG ((EFI_D_ERROR, "PartitionDriverBindingStop: Still has child.\n"));
428 return EFI_DEVICE_ERROR;
429 }
430
431 //
432 // Close the bus driver
433 //
434 gBS->CloseProtocol (
435 ControllerHandle,
437 This->DriverBindingHandle,
438 ControllerHandle
439 );
440 //
441 // Close Parent BlockIO2 if has.
442 //
443 gBS->CloseProtocol (
444 ControllerHandle,
446 This->DriverBindingHandle,
447 ControllerHandle
448 );
449
450 gBS->CloseProtocol (
451 ControllerHandle,
453 This->DriverBindingHandle,
454 ControllerHandle
455 );
456 return EFI_SUCCESS;
457 }
458
459 AllChildrenStopped = TRUE;
460 for (Index = 0; Index < NumberOfChildren; Index++) {
461 gBS->OpenProtocol (
462 ChildHandleBuffer[Index],
464 (VOID **)&BlockIo,
465 This->DriverBindingHandle,
466 ControllerHandle,
467 EFI_OPEN_PROTOCOL_GET_PROTOCOL
468 );
469 //
470 // Try to locate BlockIo2.
471 //
472 gBS->OpenProtocol (
473 ChildHandleBuffer[Index],
474 &gEfiBlockIo2ProtocolGuid,
475 (VOID **)&BlockIo2,
476 This->DriverBindingHandle,
477 ControllerHandle,
478 EFI_OPEN_PROTOCOL_GET_PROTOCOL
479 );
480
481 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
482 if (Private->InStop) {
483 //
484 // If the child handle is going to be stopped again during the re-entry
485 // of DriverBindingStop, just do nothing.
486 //
487 break;
488 }
489
490 Private->InStop = TRUE;
491
492 BlockIo->FlushBlocks (BlockIo);
493
494 if (BlockIo2 != NULL) {
495 Status = BlockIo2->FlushBlocksEx (BlockIo2, NULL);
496 DEBUG ((EFI_D_ERROR, "PartitionDriverBindingStop: FlushBlocksEx returned with %r\n", Status));
497 } else {
498 Status = EFI_SUCCESS;
499 }
500
501 gBS->CloseProtocol (
502 ControllerHandle,
504 This->DriverBindingHandle,
505 ChildHandleBuffer[Index]
506 );
507
508 if (IsZeroGuid (&Private->TypeGuid)) {
509 TypeGuid = NULL;
510 } else {
511 TypeGuid = &Private->TypeGuid;
512 }
513
514 //
515 // All Software protocols have be freed from the handle so remove it.
516 // Remove the BlockIo Protocol if has.
517 // Remove the BlockIo2 Protocol if has.
518 //
519 if (BlockIo2 != NULL) {
520 //
521 // Some device drivers might re-install the BlockIO(2) protocols for a
522 // media change condition. Therefore, if the FlushBlocksEx returned with
523 // EFI_MEDIA_CHANGED, just let the BindingStop fail to avoid potential
524 // reference of already stopped child handle.
525 //
526 if (Status != EFI_MEDIA_CHANGED) {
527 Status = gBS->UninstallMultipleProtocolInterfaces (
528 ChildHandleBuffer[Index],
530 Private->DevicePath,
532 &Private->BlockIo,
533 &gEfiBlockIo2ProtocolGuid,
534 &Private->BlockIo2,
535 &gEfiPartitionInfoProtocolGuid,
536 &Private->PartitionInfo,
538 &Private->ApplePartitionInfo,
539 TypeGuid,
540 NULL,
541 NULL
542 );
543 }
544 } else {
545 Status = gBS->UninstallMultipleProtocolInterfaces (
546 ChildHandleBuffer[Index],
548 Private->DevicePath,
550 &Private->BlockIo,
551 &gEfiPartitionInfoProtocolGuid,
552 &Private->PartitionInfo,
554 &Private->ApplePartitionInfo,
555 TypeGuid,
556 NULL,
557 NULL
558 );
559 }
560
561 if (EFI_ERROR (Status)) {
562 Private->InStop = FALSE;
563 gBS->OpenProtocol (
564 ControllerHandle,
566 (VOID **)&DiskIo,
567 This->DriverBindingHandle,
568 ChildHandleBuffer[Index],
569 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
570 );
571 } else {
572 FreePool (Private->DevicePath);
573 FreePool (Private);
574 }
575
576 if (EFI_ERROR (Status)) {
577 AllChildrenStopped = FALSE;
578 if (Status == EFI_MEDIA_CHANGED) {
579 break;
580 }
581 }
582 }
583
584 if (!AllChildrenStopped) {
585 return EFI_DEVICE_ERROR;
586 }
587
588 return EFI_SUCCESS;
589}
590
602EFI_STATUS
603EFIAPI
605 IN EFI_BLOCK_IO_PROTOCOL *This,
606 IN BOOLEAN ExtendedVerification
607 )
608{
609 PARTITION_PRIVATE_DATA *Private;
610
612
613 return Private->ParentBlockIo->Reset (
614 Private->ParentBlockIo,
615 ExtendedVerification
616 );
617}
618
632EFI_STATUS
634 IN EFI_DISK_IO_PROTOCOL *DiskIo,
635 IN UINT32 MediaId,
636 IN EFI_STATUS DefaultStatus
637 )
638{
639 EFI_STATUS Status;
640 UINT8 Buffer[1];
641
642 //
643 // Read 1 byte from offset 0 to check if the MediaId is still valid.
644 // The reading operation is synchronious thus it is not worth it to
645 // allocate a buffer from the pool. The destination buffer for the
646 // data is in the stack.
647 //
648 Status = DiskIo->ReadDisk (DiskIo, MediaId, 0, 1, (VOID *)Buffer);
649 if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
650 return Status;
651 }
652
653 return DefaultStatus;
654}
655
675EFI_STATUS
676EFIAPI
678 IN EFI_BLOCK_IO_PROTOCOL *This,
679 IN UINT32 MediaId,
680 IN EFI_LBA Lba,
681 IN UINTN BufferSize,
682 OUT VOID *Buffer
683 )
684{
685 PARTITION_PRIVATE_DATA *Private;
686 UINT64 Offset;
687
689
690 if (BufferSize % Private->BlockSize != 0) {
691 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
692 }
693
694 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
695 if (Offset + BufferSize > Private->End) {
696 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
697 }
698
699 //
700 // Because some kinds of partition have different block size from their parent
701 // device, we call the Disk IO protocol on the parent device, not the Block IO
702 // protocol
703 //
704 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
705}
706
727EFI_STATUS
728EFIAPI
730 IN EFI_BLOCK_IO_PROTOCOL *This,
731 IN UINT32 MediaId,
732 IN EFI_LBA Lba,
733 IN UINTN BufferSize,
734 IN VOID *Buffer
735 )
736{
737 PARTITION_PRIVATE_DATA *Private;
738 UINT64 Offset;
739
741
742 if (BufferSize % Private->BlockSize != 0) {
743 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
744 }
745
746 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
747 if (Offset + BufferSize > Private->End) {
748 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
749 }
750
751 //
752 // Because some kinds of partition have different block size from their parent
753 // device, we call the Disk IO protocol on the parent device, not the Block IO
754 // protocol
755 //
756 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
757}
758
769EFI_STATUS
770EFIAPI
772 IN EFI_BLOCK_IO_PROTOCOL *This
773 )
774{
775 PARTITION_PRIVATE_DATA *Private;
776
778
779 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
780}
781
795EFI_STATUS
797 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
798 IN UINT32 MediaId,
799 IN EFI_STATUS DefaultStatus
800 )
801{
802 EFI_STATUS Status;
803 UINT8 Buffer[1];
804
805 //
806 // Read 1 byte from offset 0 to check if the MediaId is still valid.
807 // The reading operation is synchronious thus it is not worth it to
808 // allocate a buffer from the pool. The destination buffer for the
809 // data is in the stack.
810 //
811 Status = DiskIo2->ReadDiskEx (DiskIo2, MediaId, 0, NULL, 1, (VOID *)Buffer);
812 if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
813 return Status;
814 }
815
816 return DefaultStatus;
817}
818
830EFI_STATUS
831EFIAPI
833 IN EFI_BLOCK_IO2_PROTOCOL *This,
834 IN BOOLEAN ExtendedVerification
835 )
836{
837 PARTITION_PRIVATE_DATA *Private;
838
840
841 return Private->ParentBlockIo2->Reset (
842 Private->ParentBlockIo2,
843 ExtendedVerification
844 );
845}
846
853VOID
854EFIAPI
856 IN EFI_EVENT Event,
857 IN VOID *Context
858 )
859{
861
862 Task = (PARTITION_ACCESS_TASK *)Context;
863
864 gBS->CloseEvent (Event);
865
866 Task->BlockIo2Token->TransactionStatus = Task->DiskIo2Token.TransactionStatus;
867 gBS->SignalEvent (Task->BlockIo2Token->Event);
868
869 FreePool (Task);
870}
871
881 IN EFI_BLOCK_IO2_TOKEN *Token
882 )
883{
884 EFI_STATUS Status;
886
887 Task = AllocatePool (sizeof (*Task));
888 if (Task == NULL) {
889 return NULL;
890 }
891
892 Status = gBS->CreateEvent (
893 EVT_NOTIFY_SIGNAL,
894 TPL_NOTIFY,
896 Task,
897 &Task->DiskIo2Token.Event
898 );
899 if (EFI_ERROR (Status)) {
900 FreePool (Task);
901 return NULL;
902 }
903
904 Task->BlockIo2Token = Token;
905
906 return Task;
907}
908
942EFI_STATUS
943EFIAPI
945 IN EFI_BLOCK_IO2_PROTOCOL *This,
946 IN UINT32 MediaId,
947 IN EFI_LBA Lba,
948 IN OUT EFI_BLOCK_IO2_TOKEN *Token,
949 IN UINTN BufferSize,
950 OUT VOID *Buffer
951 )
952{
953 EFI_STATUS Status;
954 PARTITION_PRIVATE_DATA *Private;
955 UINT64 Offset;
957
959
960 if (BufferSize % Private->BlockSize != 0) {
961 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
962 }
963
964 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
965 if (Offset + BufferSize > Private->End) {
966 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
967 }
968
969 if ((Token != NULL) && (Token->Event != NULL)) {
970 Task = PartitionCreateAccessTask (Token);
971 if (Task == NULL) {
972 return EFI_OUT_OF_RESOURCES;
973 }
974
975 Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
976 if (EFI_ERROR (Status)) {
977 gBS->CloseEvent (Task->DiskIo2Token.Event);
978 FreePool (Task);
979 }
980 } else {
981 Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
982 }
983
984 return Status;
985}
986
1018EFI_STATUS
1019EFIAPI
1021 IN EFI_BLOCK_IO2_PROTOCOL *This,
1022 IN UINT32 MediaId,
1023 IN EFI_LBA Lba,
1024 IN OUT EFI_BLOCK_IO2_TOKEN *Token,
1025 IN UINTN BufferSize,
1026 IN VOID *Buffer
1027 )
1028{
1029 EFI_STATUS Status;
1030 PARTITION_PRIVATE_DATA *Private;
1031 UINT64 Offset;
1033
1034 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
1035
1036 if (BufferSize % Private->BlockSize != 0) {
1037 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
1038 }
1039
1040 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
1041 if (Offset + BufferSize > Private->End) {
1042 return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
1043 }
1044
1045 if ((Token != NULL) && (Token->Event != NULL)) {
1046 Task = PartitionCreateAccessTask (Token);
1047 if (Task == NULL) {
1048 return EFI_OUT_OF_RESOURCES;
1049 }
1050
1051 Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
1052 if (EFI_ERROR (Status)) {
1053 gBS->CloseEvent (Task->DiskIo2Token.Event);
1054 FreePool (Task);
1055 }
1056 } else {
1057 Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
1058 }
1059
1060 return Status;
1061}
1062
1085EFI_STATUS
1086EFIAPI
1088 IN EFI_BLOCK_IO2_PROTOCOL *This,
1089 IN OUT EFI_BLOCK_IO2_TOKEN *Token
1090 )
1091{
1092 EFI_STATUS Status;
1093 PARTITION_PRIVATE_DATA *Private;
1095
1096 Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
1097
1098 if ((Token != NULL) && (Token->Event != NULL)) {
1099 Task = PartitionCreateAccessTask (Token);
1100 if (Task == NULL) {
1101 return EFI_OUT_OF_RESOURCES;
1102 }
1103
1104 Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, &Task->DiskIo2Token);
1105 if (EFI_ERROR (Status)) {
1106 gBS->CloseEvent (Task->DiskIo2Token.Event);
1107 FreePool (Task);
1108 }
1109 } else {
1110 Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, NULL);
1111 }
1112
1113 return Status;
1114}
1115
1139EFI_STATUS
1141 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1142 IN EFI_HANDLE ParentHandle,
1143 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
1144 IN EFI_DISK_IO2_PROTOCOL *ParentDiskIo2,
1145 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
1146 IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2,
1147 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
1148 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
1149 IN EFI_PARTITION_INFO_PROTOCOL *PartitionInfo,
1150 IN APPLE_PARTITION_INFO_PROTOCOL *ApplePartitionInfo,
1151 IN EFI_LBA Start,
1152 IN EFI_LBA End,
1153 IN UINT32 BlockSize,
1154 IN EFI_GUID *TypeGuid
1155 )
1156{
1157 EFI_STATUS Status;
1158 PARTITION_PRIVATE_DATA *Private;
1159
1160 Status = EFI_SUCCESS;
1161 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));
1162 if (Private == NULL) {
1163 return EFI_OUT_OF_RESOURCES;
1164 }
1165
1167
1168 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);
1169 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);
1170
1171 Private->BlockSize = BlockSize;
1172 Private->ParentBlockIo = ParentBlockIo;
1173 Private->ParentBlockIo2 = ParentBlockIo2;
1174 Private->DiskIo = ParentDiskIo;
1175 Private->DiskIo2 = ParentDiskIo2;
1176
1177 //
1178 // Set the BlockIO into Private Data.
1179 //
1180 Private->BlockIo.Revision = ParentBlockIo->Revision;
1181
1182 Private->BlockIo.Media = &Private->Media;
1183 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
1184
1185 Private->BlockIo.Reset = PartitionReset;
1186 Private->BlockIo.ReadBlocks = PartitionReadBlocks;
1187 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;
1188 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;
1189
1190 //
1191 // Set the BlockIO2 into Private Data.
1192 //
1193 if (Private->DiskIo2 != NULL) {
1194 ASSERT (Private->ParentBlockIo2 != NULL);
1195 Private->BlockIo2.Media = &Private->Media2;
1196 CopyMem (Private->BlockIo2.Media, ParentBlockIo2->Media, sizeof (EFI_BLOCK_IO_MEDIA));
1197
1198 Private->BlockIo2.Reset = PartitionResetEx;
1199 Private->BlockIo2.ReadBlocksEx = PartitionReadBlocksEx;
1200 Private->BlockIo2.WriteBlocksEx = PartitionWriteBlocksEx;
1201 Private->BlockIo2.FlushBlocksEx = PartitionFlushBlocksEx;
1202 }
1203
1204 Private->Media.IoAlign = 0;
1205 Private->Media.LogicalPartition = TRUE;
1206 Private->Media.LastBlock = DivU64x32 (
1207 MultU64x32 (
1208 End - Start + 1,
1209 ParentBlockIo->Media->BlockSize
1210 ),
1211 BlockSize
1212 ) - 1;
1213
1214 Private->Media.BlockSize = (UINT32)BlockSize;
1215
1216 Private->Media2.IoAlign = 0;
1217 Private->Media2.LogicalPartition = TRUE;
1218 Private->Media2.LastBlock = Private->Media.LastBlock;
1219 Private->Media2.BlockSize = (UINT32)BlockSize;
1220
1221 //
1222 // Per UEFI Spec, LowestAlignedLba, LogicalBlocksPerPhysicalBlock and OptimalTransferLengthGranularity must be 0
1223 // for logical partitions.
1224 //
1225 if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {
1226 Private->Media.LowestAlignedLba = 0;
1227 Private->Media.LogicalBlocksPerPhysicalBlock = 0;
1228 Private->Media2.LowestAlignedLba = 0;
1229 Private->Media2.LogicalBlocksPerPhysicalBlock = 0;
1230 if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION3) {
1231 Private->Media.OptimalTransferLengthGranularity = 0;
1232 Private->Media2.OptimalTransferLengthGranularity = 0;
1233 }
1234 }
1235
1236 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);
1237
1238 if (Private->DevicePath == NULL) {
1239 FreePool (Private);
1240 return EFI_OUT_OF_RESOURCES;
1241 }
1242
1243 //
1244 // Set the PartitionInfo into Private Data.
1245 //
1246 CopyMem (&Private->PartitionInfo, PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
1247 CopyMem (&Private->ApplePartitionInfo, ApplePartitionInfo, sizeof (APPLE_PARTITION_INFO_PROTOCOL));
1248
1249 if (TypeGuid != NULL) {
1250 CopyGuid (&(Private->TypeGuid), TypeGuid);
1251 } else {
1252 ZeroMem ((VOID *)&(Private->TypeGuid), sizeof (EFI_GUID));
1253 }
1254
1255 //
1256 // Create the new handle.
1257 //
1258 Private->Handle = NULL;
1259 if (Private->DiskIo2 != NULL) {
1260 Status = gBS->InstallMultipleProtocolInterfaces (
1261 &Private->Handle,
1263 Private->DevicePath,
1265 &Private->BlockIo,
1266 &gEfiBlockIo2ProtocolGuid,
1267 &Private->BlockIo2,
1268 &gEfiPartitionInfoProtocolGuid,
1269 &Private->PartitionInfo,
1271 &Private->ApplePartitionInfo,
1272 TypeGuid,
1273 NULL,
1274 NULL
1275 );
1276 } else {
1277 Status = gBS->InstallMultipleProtocolInterfaces (
1278 &Private->Handle,
1280 Private->DevicePath,
1282 &Private->BlockIo,
1283 &gEfiPartitionInfoProtocolGuid,
1284 &Private->PartitionInfo,
1286 &Private->ApplePartitionInfo,
1287 TypeGuid,
1288 NULL,
1289 NULL
1290 );
1291 }
1292
1293 if (!EFI_ERROR (Status)) {
1294 //
1295 // Open the Parent Handle for the child
1296 //
1297 Status = gBS->OpenProtocol (
1298 ParentHandle,
1300 (VOID **)&ParentDiskIo,
1301 This->DriverBindingHandle,
1302 Private->Handle,
1303 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1304 );
1305 } else {
1306 FreePool (Private->DevicePath);
1307 FreePool (Private);
1308
1309 //
1310 // if the Status == EFI_ALREADY_STARTED, it means the child handles
1311 // are already installed. So return EFI_SUCCESS to avoid do the next
1312 // partition type check.
1313 //
1314 if (Status == EFI_ALREADY_STARTED) {
1315 Status = EFI_SUCCESS;
1316 }
1317 }
1318
1319 return Status;
1320}
1321
1332EFI_STATUS
1333EFIAPI
1335 IN EFI_HANDLE ImageHandle,
1336 IN EFI_SYSTEM_TABLE *SystemTable
1337 )
1338{
1339 EFI_STATUS Status;
1340
1341 //
1342 // Install driver model protocol(s).
1343 //
1344 Status = EfiLibInstallDriverBindingComponentName2 (
1345 ImageHandle,
1346 SystemTable,
1348 ImageHandle,
1351 );
1352 ASSERT_EFI_ERROR (Status);
1353
1354 return Status;
1355}
1356
1366BOOLEAN
1368 IN EFI_HANDLE ControllerHandle
1369 )
1370{
1371 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
1372 UINTN EntryCount;
1373 EFI_STATUS Status;
1374 UINTN Index;
1375
1376 Status = gBS->OpenProtocolInformation (
1377 ControllerHandle,
1379 &OpenInfoBuffer,
1380 &EntryCount
1381 );
1382 ASSERT_EFI_ERROR (Status);
1383
1384 for (Index = 0; Index < EntryCount; Index++) {
1385 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
1386 break;
1387 }
1388 }
1389
1390 FreePool (OpenInfoBuffer);
1391
1392 return (BOOLEAN)(Index < EntryCount);
1393}
EFI_STATUS PartitionInstallAppleChildHandles(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_DISK_IO2_PROTOCOL *DiskIo2, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
Definition Apm.c:29
UINT16 BlockSize
Definition Apm.h:32
EFI_GUID gApplePartitionInfoProtocolGuid
UINT64 Start
EFI_DEVICE_PATH_PROTOCOL End
VOID EFIAPI Exit(IN EFI_STATUS Status)
EFI_STATUS PartitionInstallGptChildHandles(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_DISK_IO2_PROTOCOL *DiskIo2, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
Definition Gpt.c:186
EFI_STATUS PartitionInstallMbrChildHandles(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_DISK_IO2_PROTOCOL *DiskIo2, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
Definition Mbr.c:118
EFI_BOOT_SERVICES * gBS
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPartitionComponentName
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPartitionComponentName2
EFI_STATUS EFIAPI PartitionWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, IN VOID *Buffer)
Definition Partition.c:729
EFI_STATUS EFIAPI PartitionResetEx(IN EFI_BLOCK_IO2_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
Definition Partition.c:832
EFI_STATUS EFIAPI PartitionWriteBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN OUT EFI_BLOCK_IO2_TOKEN *Token, IN UINTN BufferSize, IN VOID *Buffer)
Definition Partition.c:1020
EFI_STATUS EFIAPI PartitionFlushBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL *This, IN OUT EFI_BLOCK_IO2_TOKEN *Token)
Definition Partition.c:1087
EFI_STATUS EFIAPI PartitionDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer)
Definition Partition.c:400
EFI_STATUS EFIAPI InitializePartition(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition Partition.c:1334
VOID EFIAPI PartitionOnAccessComplete(IN EFI_EVENT Event, IN VOID *Context)
Definition Partition.c:855
EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding
Definition Partition.c:18
EFI_STATUS EFIAPI PartitionDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition Partition.c:71
EFI_STATUS EFIAPI PartitionReadBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN OUT EFI_BLOCK_IO2_TOKEN *Token, IN UINTN BufferSize, OUT VOID *Buffer)
Definition Partition.c:944
BOOLEAN HasChildren(IN EFI_HANDLE ControllerHandle)
Definition Partition.c:1367
EFI_STATUS EFIAPI PartitionDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition Partition.c:195
EFI_STATUS ProbeMediaStatusEx(IN EFI_DISK_IO2_PROTOCOL *DiskIo2, IN UINT32 MediaId, IN EFI_STATUS DefaultStatus)
Definition Partition.c:796
EFI_STATUS EFIAPI PartitionFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL *This)
Definition Partition.c:771
EFI_STATUS PartitionInstallChildHandle(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ParentHandle, IN EFI_DISK_IO_PROTOCOL *ParentDiskIo, IN EFI_DISK_IO2_PROTOCOL *ParentDiskIo2, IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo, IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, IN EFI_PARTITION_INFO_PROTOCOL *PartitionInfo, IN APPLE_PARTITION_INFO_PROTOCOL *ApplePartitionInfo, IN EFI_LBA Start, IN EFI_LBA End, IN UINT32 BlockSize, IN EFI_GUID *TypeGuid)
Definition Partition.c:1140
EFI_STATUS EFIAPI PartitionReset(IN EFI_BLOCK_IO_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
Definition Partition.c:604
PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[]
Definition Partition.c:46
PARTITION_ACCESS_TASK * PartitionCreateAccessTask(IN EFI_BLOCK_IO2_TOKEN *Token)
Definition Partition.c:880
EFI_STATUS EFIAPI PartitionReadBlocks(IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, OUT VOID *Buffer)
Definition Partition.c:677
EFI_STATUS ProbeMediaStatus(IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UINT32 MediaId, IN EFI_STATUS DefaultStatus)
Definition Partition.c:633
#define PARTITION_PRIVATE_DATA_SIGNATURE
Definition Partition.h:44
#define PARTITION_DEVICE_FROM_BLOCK_IO_THIS(a)
Definition Partition.h:75
#define PARTITION_DEVICE_FROM_BLOCK_IO2_THIS(a)
Definition Partition.h:76
EFI_STATUS(* PARTITION_DETECT_ROUTINE)(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_DISK_IO2_PROTOCOL *DiskIo2, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
Definition Partition.h:507
EFI_STATUS PartitionInstallUdfChildHandles(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_DISK_IO2_PROTOCOL *DiskIo2, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
Definition Udf.c:738
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
BOOLEAN EFIAPI IsZeroGuid(IN CONST GUID *Guid)
EFI_GUID gEfiDiskIo2ProtocolGuid
EFI_GUID gEfiBlockIoProtocolGuid
EFI_GUID gEfiDiskIoProtocolGuid
EFI_GUID gEfiDevicePathProtocolGuid
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition UserMath.c:96
#define ASSERT(x)
Definition coder.h:55
#define DivU64x32(x, y, z)
EFI_BLOCK_IO2_TOKEN * BlockIo2Token
Definition Partition.h:72
EFI_DISK_IO2_TOKEN DiskIo2Token
Definition Partition.h:71
EFI_BLOCK_IO_MEDIA Media2
Definition Partition.h:53
APPLE_PARTITION_INFO_PROTOCOL ApplePartitionInfo
Definition Partition.h:67
EFI_BLOCK_IO_PROTOCOL * ParentBlockIo
Definition Partition.h:58
EFI_BLOCK_IO_PROTOCOL BlockIo
Definition Partition.h:50
EFI_DISK_IO2_PROTOCOL * DiskIo2
Definition Partition.h:57
EFI_BLOCK_IO_MEDIA Media
Definition Partition.h:52
EFI_DISK_IO_PROTOCOL * DiskIo
Definition Partition.h:56
EFI_PARTITION_INFO_PROTOCOL PartitionInfo
Definition Partition.h:54
EFI_DEVICE_PATH_PROTOCOL * DevicePath
Definition Partition.h:49
EFI_BLOCK_IO2_PROTOCOL BlockIo2
Definition Partition.h:51
EFI_BLOCK_IO2_PROTOCOL * ParentBlockIo2
Definition Partition.h:59