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