]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
Change BlockIo drivers to return EFI_NO_MEDIA or EFI_MEDIA_CHANGED even the Buffer...
[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", Legacy
5 MBR, and GPT partition schemes are supported.
6
7 Copyright (c) 2006 - 2011, 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 0xa,
29 NULL,
30 NULL
31 };
32
33 //
34 // Prioritized function list to detect partition table.
35 //
36 PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
37 PartitionInstallGptChildHandles,
38 PartitionInstallElToritoChildHandles,
39 PartitionInstallMbrChildHandles,
40 NULL
41 };
42
43
44
45 /**
46 Test to see if this driver supports ControllerHandle. Any ControllerHandle
47 than contains a BlockIo and DiskIo protocol can be supported.
48
49 @param This Protocol instance pointer.
50 @param ControllerHandle Handle of device to test
51 @param RemainingDevicePath Optional parameter use to pick a specific child
52 device to start.
53
54 @retval EFI_SUCCESS This driver supports this device
55 @retval EFI_ALREADY_STARTED This driver is already running on this device
56 @retval other This driver does not support this device
57
58 **/
59 EFI_STATUS
60 EFIAPI
61 PartitionDriverBindingSupported (
62 IN EFI_DRIVER_BINDING_PROTOCOL *This,
63 IN EFI_HANDLE ControllerHandle,
64 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
65 )
66 {
67 EFI_STATUS Status;
68 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
69 EFI_DISK_IO_PROTOCOL *DiskIo;
70 EFI_DEV_PATH *Node;
71
72 //
73 // Check RemainingDevicePath validation
74 //
75 if (RemainingDevicePath != NULL) {
76 //
77 // Check if RemainingDevicePath is the End of Device Path Node,
78 // if yes, go on checking other conditions
79 //
80 if (!IsDevicePathEnd (RemainingDevicePath)) {
81 //
82 // If RemainingDevicePath isn't the End of Device Path Node,
83 // check its validation
84 //
85 Node = (EFI_DEV_PATH *) RemainingDevicePath;
86 if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||
87 Node->DevPath.SubType != MEDIA_HARDDRIVE_DP ||
88 DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)) {
89 return EFI_UNSUPPORTED;
90 }
91 }
92 }
93
94 //
95 // Open the IO Abstraction(s) needed to perform the supported test
96 //
97 Status = gBS->OpenProtocol (
98 ControllerHandle,
99 &gEfiDiskIoProtocolGuid,
100 (VOID **) &DiskIo,
101 This->DriverBindingHandle,
102 ControllerHandle,
103 EFI_OPEN_PROTOCOL_BY_DRIVER
104 );
105 if (Status == EFI_ALREADY_STARTED) {
106 return EFI_SUCCESS;
107 }
108
109 if (EFI_ERROR (Status)) {
110 return Status;
111 }
112 //
113 // Close the I/O Abstraction(s) used to perform the supported test
114 //
115 gBS->CloseProtocol (
116 ControllerHandle,
117 &gEfiDiskIoProtocolGuid,
118 This->DriverBindingHandle,
119 ControllerHandle
120 );
121
122 //
123 // Open the EFI Device Path protocol needed to perform the supported test
124 //
125 Status = gBS->OpenProtocol (
126 ControllerHandle,
127 &gEfiDevicePathProtocolGuid,
128 (VOID **) &ParentDevicePath,
129 This->DriverBindingHandle,
130 ControllerHandle,
131 EFI_OPEN_PROTOCOL_BY_DRIVER
132 );
133 if (Status == EFI_ALREADY_STARTED) {
134 return EFI_SUCCESS;
135 }
136
137 if (EFI_ERROR (Status)) {
138 return Status;
139 }
140
141 //
142 // Close protocol, don't use device path protocol in the Support() function
143 //
144 gBS->CloseProtocol (
145 ControllerHandle,
146 &gEfiDevicePathProtocolGuid,
147 This->DriverBindingHandle,
148 ControllerHandle
149 );
150
151 //
152 // Open the IO Abstraction(s) needed to perform the supported test
153 //
154 Status = gBS->OpenProtocol (
155 ControllerHandle,
156 &gEfiBlockIoProtocolGuid,
157 NULL,
158 This->DriverBindingHandle,
159 ControllerHandle,
160 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
161 );
162
163 return Status;
164 }
165
166
167 /**
168 Start this driver on ControllerHandle by opening a Block IO and Disk IO
169 protocol, reading Device Path, and creating a child handle with a
170 Disk IO and device path protocol.
171
172 @param This Protocol instance pointer.
173 @param ControllerHandle Handle of device to bind driver to
174 @param RemainingDevicePath Optional parameter use to pick a specific child
175 device to start.
176
177 @retval EFI_SUCCESS This driver is added to ControllerHandle
178 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
179 @retval other This driver does not support this device
180
181 **/
182 EFI_STATUS
183 EFIAPI
184 PartitionDriverBindingStart (
185 IN EFI_DRIVER_BINDING_PROTOCOL *This,
186 IN EFI_HANDLE ControllerHandle,
187 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
188 )
189 {
190 EFI_STATUS Status;
191 EFI_STATUS OpenStatus;
192 EFI_BLOCK_IO_PROTOCOL *BlockIo;
193 EFI_DISK_IO_PROTOCOL *DiskIo;
194 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
195 PARTITION_DETECT_ROUTINE *Routine;
196 BOOLEAN MediaPresent;
197 EFI_TPL OldTpl;
198
199 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
200 //
201 // Check RemainingDevicePath validation
202 //
203 if (RemainingDevicePath != NULL) {
204 //
205 // Check if RemainingDevicePath is the End of Device Path Node,
206 // if yes, return EFI_SUCCESS
207 //
208 if (IsDevicePathEnd (RemainingDevicePath)) {
209 Status = EFI_SUCCESS;
210 goto Exit;
211 }
212 }
213
214 Status = gBS->OpenProtocol (
215 ControllerHandle,
216 &gEfiBlockIoProtocolGuid,
217 (VOID **) &BlockIo,
218 This->DriverBindingHandle,
219 ControllerHandle,
220 EFI_OPEN_PROTOCOL_GET_PROTOCOL
221 );
222 if (EFI_ERROR (Status)) {
223 goto Exit;
224 }
225 //
226 // Get the Device Path Protocol on ControllerHandle's handle
227 //
228 Status = gBS->OpenProtocol (
229 ControllerHandle,
230 &gEfiDevicePathProtocolGuid,
231 (VOID **) &ParentDevicePath,
232 This->DriverBindingHandle,
233 ControllerHandle,
234 EFI_OPEN_PROTOCOL_BY_DRIVER
235 );
236 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
237 goto Exit;
238 }
239
240 Status = gBS->OpenProtocol (
241 ControllerHandle,
242 &gEfiDiskIoProtocolGuid,
243 (VOID **) &DiskIo,
244 This->DriverBindingHandle,
245 ControllerHandle,
246 EFI_OPEN_PROTOCOL_BY_DRIVER
247 );
248 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
249 gBS->CloseProtocol (
250 ControllerHandle,
251 &gEfiDevicePathProtocolGuid,
252 This->DriverBindingHandle,
253 ControllerHandle
254 );
255 goto Exit;
256 }
257
258 OpenStatus = Status;
259
260 //
261 // Try to read blocks when there's media or it is removable physical partition.
262 //
263 Status = EFI_UNSUPPORTED;
264 MediaPresent = BlockIo->Media->MediaPresent;
265 if (BlockIo->Media->MediaPresent ||
266 (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) {
267 //
268 // Try for GPT, then El Torito, and then legacy MBR partition types. If the
269 // media supports a given partition type install child handles to represent
270 // the partitions described by the media.
271 //
272 Routine = &mPartitionDetectRoutineTable[0];
273 while (*Routine != NULL) {
274 Status = (*Routine) (
275 This,
276 ControllerHandle,
277 DiskIo,
278 BlockIo,
279 ParentDevicePath
280 );
281 if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {
282 break;
283 }
284 Routine++;
285 }
286 }
287 //
288 // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),
289 // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the
290 // driver. So don't try to close them. Otherwise, we will break the dependency
291 // between the controller and the driver set up before.
292 //
293 // In the case that when the media changes on a device it will Reinstall the
294 // BlockIo interaface. This will cause a call to our Stop(), and a subsequent
295 // reentrant call to our Start() successfully. We should leave the device open
296 // when this happen. The "media change" case includes either the status is
297 // EFI_MEDIA_CHANGED or it is a "media" to "no media" change.
298 //
299 if (EFI_ERROR (Status) &&
300 !EFI_ERROR (OpenStatus) &&
301 Status != EFI_MEDIA_CHANGED &&
302 !(MediaPresent && Status == EFI_NO_MEDIA)) {
303 gBS->CloseProtocol (
304 ControllerHandle,
305 &gEfiDiskIoProtocolGuid,
306 This->DriverBindingHandle,
307 ControllerHandle
308 );
309
310 gBS->CloseProtocol (
311 ControllerHandle,
312 &gEfiDevicePathProtocolGuid,
313 This->DriverBindingHandle,
314 ControllerHandle
315 );
316 }
317
318 Exit:
319 gBS->RestoreTPL (OldTpl);
320 return Status;
321 }
322
323
324 /**
325 Stop this driver on ControllerHandle. Support stopping any child handles
326 created by this driver.
327
328 @param This Protocol instance pointer.
329 @param ControllerHandle Handle of device to stop driver on
330 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
331 children is zero stop the entire bus driver.
332 @param ChildHandleBuffer List of Child Handles to Stop.
333
334 @retval EFI_SUCCESS This driver is removed ControllerHandle
335 @retval other This driver was not removed from this device
336
337 **/
338 EFI_STATUS
339 EFIAPI
340 PartitionDriverBindingStop (
341 IN EFI_DRIVER_BINDING_PROTOCOL *This,
342 IN EFI_HANDLE ControllerHandle,
343 IN UINTN NumberOfChildren,
344 IN EFI_HANDLE *ChildHandleBuffer
345 )
346 {
347 EFI_STATUS Status;
348 UINTN Index;
349 EFI_BLOCK_IO_PROTOCOL *BlockIo;
350 BOOLEAN AllChildrenStopped;
351 PARTITION_PRIVATE_DATA *Private;
352 EFI_DISK_IO_PROTOCOL *DiskIo;
353
354 if (NumberOfChildren == 0) {
355 //
356 // Close the bus driver
357 //
358 gBS->CloseProtocol (
359 ControllerHandle,
360 &gEfiDiskIoProtocolGuid,
361 This->DriverBindingHandle,
362 ControllerHandle
363 );
364
365 gBS->CloseProtocol (
366 ControllerHandle,
367 &gEfiDevicePathProtocolGuid,
368 This->DriverBindingHandle,
369 ControllerHandle
370 );
371
372 return EFI_SUCCESS;
373 }
374
375 AllChildrenStopped = TRUE;
376 for (Index = 0; Index < NumberOfChildren; Index++) {
377 Status = gBS->OpenProtocol (
378 ChildHandleBuffer[Index],
379 &gEfiBlockIoProtocolGuid,
380 (VOID **) &BlockIo,
381 This->DriverBindingHandle,
382 ControllerHandle,
383 EFI_OPEN_PROTOCOL_GET_PROTOCOL
384 );
385 if (!EFI_ERROR (Status)) {
386
387 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
388
389 //
390 // All Software protocols have be freed from the handle so remove it.
391 //
392 BlockIo->FlushBlocks (BlockIo);
393
394 Status = gBS->CloseProtocol (
395 ControllerHandle,
396 &gEfiDiskIoProtocolGuid,
397 This->DriverBindingHandle,
398 ChildHandleBuffer[Index]
399 );
400
401 Status = gBS->UninstallMultipleProtocolInterfaces (
402 ChildHandleBuffer[Index],
403 &gEfiDevicePathProtocolGuid,
404 Private->DevicePath,
405 &gEfiBlockIoProtocolGuid,
406 &Private->BlockIo,
407 Private->EspGuid,
408 NULL,
409 NULL
410 );
411 if (EFI_ERROR (Status)) {
412 gBS->OpenProtocol (
413 ControllerHandle,
414 &gEfiDiskIoProtocolGuid,
415 (VOID **) &DiskIo,
416 This->DriverBindingHandle,
417 ChildHandleBuffer[Index],
418 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
419 );
420 } else {
421 FreePool (Private->DevicePath);
422 FreePool (Private);
423 }
424
425 }
426
427 if (EFI_ERROR (Status)) {
428 AllChildrenStopped = FALSE;
429 }
430 }
431
432 if (!AllChildrenStopped) {
433 return EFI_DEVICE_ERROR;
434 }
435
436 return EFI_SUCCESS;
437 }
438
439
440 /**
441 Reset the Block Device.
442
443 @param This Protocol instance pointer.
444 @param ExtendedVerification Driver may perform diagnostics on reset.
445
446 @retval EFI_SUCCESS The device was reset.
447 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
448 not be reset.
449
450 **/
451 EFI_STATUS
452 EFIAPI
453 PartitionReset (
454 IN EFI_BLOCK_IO_PROTOCOL *This,
455 IN BOOLEAN ExtendedVerification
456 )
457 {
458 PARTITION_PRIVATE_DATA *Private;
459
460 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
461
462 return Private->ParentBlockIo->Reset (
463 Private->ParentBlockIo,
464 ExtendedVerification
465 );
466 }
467
468 /**
469 Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
470 for no media or media change case. Otherwise DefaultStatus is returned.
471
472 @param DiskIo Pointer to the DiskIo instance.
473 @param MediaId Id of the media, changes every time the media is replaced.
474 @param DefaultStatus The default status to return when it's not the no media
475 or media change case.
476
477 @retval EFI_NO_MEDIA There is no media.
478 @retval EFI_MEDIA_CHANGED The media was changed.
479 @retval others The default status to return.
480 **/
481 EFI_STATUS
482 ProbeMediaStatus (
483 IN EFI_DISK_IO_PROTOCOL *DiskIo,
484 IN UINT32 MediaId,
485 IN EFI_STATUS DefaultStatus
486 )
487 {
488 EFI_STATUS Status;
489
490 //
491 // Read 1 byte from offset 0 but passing NULL as buffer pointer
492 //
493 Status = DiskIo->ReadDisk (DiskIo, MediaId, 0, 1, NULL);
494 if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
495 return Status;
496 }
497 return DefaultStatus;
498 }
499
500 /**
501 Read by using the Disk IO protocol on the parent device. Lba addresses
502 must be converted to byte offsets.
503
504 @param This Protocol instance pointer.
505 @param MediaId Id of the media, changes every time the media is replaced.
506 @param Lba The starting Logical Block Address to read from
507 @param BufferSize Size of Buffer, must be a multiple of device block size.
508 @param Buffer Buffer containing read data
509
510 @retval EFI_SUCCESS The data was read correctly from the device.
511 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
512 @retval EFI_NO_MEDIA There is no media in the device.
513 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
514 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
515 @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
516 valid for the device.
517
518 **/
519 EFI_STATUS
520 EFIAPI
521 PartitionReadBlocks (
522 IN EFI_BLOCK_IO_PROTOCOL *This,
523 IN UINT32 MediaId,
524 IN EFI_LBA Lba,
525 IN UINTN BufferSize,
526 OUT VOID *Buffer
527 )
528 {
529 PARTITION_PRIVATE_DATA *Private;
530 UINT64 Offset;
531
532 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
533
534 if (BufferSize % Private->BlockSize != 0) {
535 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
536 }
537
538 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
539 if (Offset + BufferSize > Private->End) {
540 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
541 }
542 //
543 // Because some kinds of partition have different block size from their parent
544 // device, we call the Disk IO protocol on the parent device, not the Block IO
545 // protocol
546 //
547 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
548 }
549
550 /**
551 Write by using the Disk IO protocol on the parent device. Lba addresses
552 must be converted to byte offsets.
553
554 @param This Protocol instance pointer.
555 @param MediaId Id of the media, changes every time the media is replaced.
556 @param Lba The starting Logical Block Address to read from
557 @param BufferSize Size of Buffer, must be a multiple of device block size.
558 @param Buffer Buffer containing read data
559
560 @retval EFI_SUCCESS The data was written correctly to the device.
561 @retval EFI_WRITE_PROTECTED The device can not be written to.
562 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
563 @retval EFI_NO_MEDIA There is no media in the device.
564 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
565 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
566 @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not
567 valid for the device.
568
569 **/
570 EFI_STATUS
571 EFIAPI
572 PartitionWriteBlocks (
573 IN EFI_BLOCK_IO_PROTOCOL *This,
574 IN UINT32 MediaId,
575 IN EFI_LBA Lba,
576 IN UINTN BufferSize,
577 OUT VOID *Buffer
578 )
579 {
580 PARTITION_PRIVATE_DATA *Private;
581 UINT64 Offset;
582
583 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
584
585 if (BufferSize % Private->BlockSize != 0) {
586 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_BAD_BUFFER_SIZE);
587 }
588
589 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
590 if (Offset + BufferSize > Private->End) {
591 return ProbeMediaStatus (Private->DiskIo, MediaId, EFI_INVALID_PARAMETER);
592 }
593 //
594 // Because some kinds of partition have different block size from their parent
595 // device, we call the Disk IO protocol on the parent device, not the Block IO
596 // protocol
597 //
598 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
599 }
600
601
602 /**
603 Flush the parent Block Device.
604
605 @param This Protocol instance pointer.
606
607 @retval EFI_SUCCESS All outstanding data was written to the device
608 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
609 @retval EFI_NO_MEDIA There is no media in the device.
610
611 **/
612 EFI_STATUS
613 EFIAPI
614 PartitionFlushBlocks (
615 IN EFI_BLOCK_IO_PROTOCOL *This
616 )
617 {
618 PARTITION_PRIVATE_DATA *Private;
619
620 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
621
622 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
623 }
624
625
626
627 /**
628 Create a child handle for a logical block device that represents the
629 bytes Start to End of the Parent Block IO device.
630
631 @param[in] This Protocol instance pointer
632 @param[in] ParentHandle Parent Handle for new child
633 @param[in] ParentDiskIo Parent DiskIo interface
634 @param[in] ParentBlockIo Parent BlockIo interface
635 @param[in] ParentDevicePath Parent Device Path
636 @param[in] DevicePathNode Child Device Path node
637 @param[in] Start Start Block
638 @param[in] End End Block
639 @param[in] BlockSize Child block size
640 @param[in] InstallEspGuid Flag to install EFI System Partition GUID on handle
641
642 @retval EFI_SUCCESS A child handle was added
643 @retval other A child handle was not added
644
645 **/
646 EFI_STATUS
647 PartitionInstallChildHandle (
648 IN EFI_DRIVER_BINDING_PROTOCOL *This,
649 IN EFI_HANDLE ParentHandle,
650 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
651 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
652 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
653 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
654 IN EFI_LBA Start,
655 IN EFI_LBA End,
656 IN UINT32 BlockSize,
657 IN BOOLEAN InstallEspGuid
658 )
659 {
660 EFI_STATUS Status;
661 PARTITION_PRIVATE_DATA *Private;
662
663 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));
664 if (Private == NULL) {
665 return EFI_OUT_OF_RESOURCES;
666 }
667
668 Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;
669
670 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);
671 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);
672
673 Private->BlockSize = BlockSize;
674 Private->ParentBlockIo = ParentBlockIo;
675 Private->DiskIo = ParentDiskIo;
676
677 Private->BlockIo.Revision = ParentBlockIo->Revision;
678
679 Private->BlockIo.Media = &Private->Media;
680 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
681 Private->Media.LogicalPartition = TRUE;
682
683 //
684 // Logical BlockIo instance doesn't have IoAlign restriction because it implements block io operation based on DiskIo
685 //
686 Private->Media.IoAlign = 0;
687 Private->Media.LastBlock = DivU64x32 (
688 MultU64x32 (
689 End - Start + 1,
690 ParentBlockIo->Media->BlockSize
691 ),
692 BlockSize
693 ) - 1;
694
695 Private->Media.BlockSize = (UINT32) BlockSize;
696
697 //
698 // Per UEFI Spec, LowestAlignedLba and LogicalBlocksPerPhysicalBlock must be 0
699 // for logical partitions.
700 //
701 if (Private->BlockIo.Revision >= EFI_BLOCK_IO_PROTOCOL_REVISION2) {
702 Private->BlockIo.Media->LowestAlignedLba = 0;
703 Private->BlockIo.Media->LogicalBlocksPerPhysicalBlock = 0;
704 }
705
706 Private->BlockIo.Reset = PartitionReset;
707 Private->BlockIo.ReadBlocks = PartitionReadBlocks;
708 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;
709 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;
710
711 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);
712
713 if (Private->DevicePath == NULL) {
714 FreePool (Private);
715 return EFI_OUT_OF_RESOURCES;
716 }
717
718 if (InstallEspGuid) {
719 Private->EspGuid = &gEfiPartTypeSystemPartGuid;
720 } else {
721 //
722 // If NULL InstallMultipleProtocolInterfaces will ignore it.
723 //
724 Private->EspGuid = NULL;
725 }
726 //
727 // Create the new handle
728 //
729 Private->Handle = NULL;
730 Status = gBS->InstallMultipleProtocolInterfaces (
731 &Private->Handle,
732 &gEfiDevicePathProtocolGuid,
733 Private->DevicePath,
734 &gEfiBlockIoProtocolGuid,
735 &Private->BlockIo,
736 Private->EspGuid,
737 NULL,
738 NULL
739 );
740
741 if (!EFI_ERROR (Status)) {
742 //
743 // Open the Parent Handle for the child
744 //
745 Status = gBS->OpenProtocol (
746 ParentHandle,
747 &gEfiDiskIoProtocolGuid,
748 (VOID **) &ParentDiskIo,
749 This->DriverBindingHandle,
750 Private->Handle,
751 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
752 );
753 } else {
754 FreePool (Private->DevicePath);
755 FreePool (Private);
756 }
757
758 return Status;
759 }
760
761
762 /**
763 The user Entry Point for module Partition. The user code starts with this function.
764
765 @param[in] ImageHandle The firmware allocated handle for the EFI image.
766 @param[in] SystemTable A pointer to the EFI System Table.
767
768 @retval EFI_SUCCESS The entry point is executed successfully.
769 @retval other Some error occurs when executing this entry point.
770
771 **/
772 EFI_STATUS
773 EFIAPI
774 InitializePartition (
775 IN EFI_HANDLE ImageHandle,
776 IN EFI_SYSTEM_TABLE *SystemTable
777 )
778 {
779 EFI_STATUS Status;
780
781 //
782 // Install driver model protocol(s).
783 //
784 Status = EfiLibInstallDriverBindingComponentName2 (
785 ImageHandle,
786 SystemTable,
787 &gPartitionDriverBinding,
788 ImageHandle,
789 &gPartitionComponentName,
790 &gPartitionComponentName2
791 );
792 ASSERT_EFI_ERROR (Status);
793
794
795 return Status;
796 }
797