]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c
Perfect the msa of the following modules, DiskIo, Partition, English and Ebc.
[mirror_edk2.git] / EdkModulePkg / Universal / Disk / Partition / Dxe / Partition.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Partition.c\r
15\r
16Abstract:\r
17\r
18 Partition driver that produces logical BlockIo devices from a physical\r
19 BlockIo device. The logical BlockIo devices are based on the format\r
20 of the raw block devices media. Currently "El Torito CD-ROM", Legacy\r
21 MBR, and GPT partition schemes are supported.\r
22\r
23--*/\r
24\r
25#include "Partition.h"\r
26\r
878ddf1f 27//\r
28// Partition Driver Global Variables\r
29//\r
30EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {\r
31 PartitionDriverBindingSupported,\r
32 PartitionDriverBindingStart,\r
33 PartitionDriverBindingStop,\r
61fb1657 34 0xa,\r
878ddf1f 35 NULL,\r
36 NULL\r
37};\r
38\r
c7c02fab 39STATIC \r
40PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {\r
41 PartitionInstallGptChildHandles,\r
42 PartitionInstallElToritoChildHandles,\r
43 PartitionInstallMbrChildHandles,\r
44 NULL\r
45};\r
46\r
47\r
878ddf1f 48EFI_STATUS\r
49EFIAPI\r
50PartitionDriverBindingSupported (\r
51 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
52 IN EFI_HANDLE ControllerHandle,\r
53 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
54 )\r
55/*++\r
56\r
57 Routine Description:\r
58 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
59 than contains a BlockIo and DiskIo protocol can be supported.\r
60\r
61 Arguments:\r
62 This - Protocol instance pointer.\r
63 ControllerHandle - Handle of device to test\r
64 RemainingDevicePath - Not used\r
65\r
66 Returns:\r
67 EFI_SUCCESS - This driver supports this device\r
68 EFI_ALREADY_STARTED - This driver is already running on this device\r
69 EFI_UNSUPPORTED - This driver does not support this device\r
70\r
71--*/\r
72{\r
73 EFI_STATUS Status;\r
74 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
75 EFI_DISK_IO_PROTOCOL *DiskIo;\r
76 EFI_DEV_PATH *Node;\r
77\r
78 if (RemainingDevicePath != NULL) {\r
79 Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
80 if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||\r
81 Node->DevPath.SubType != MEDIA_HARDDRIVE_DP ||\r
82 DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)\r
83 ) {\r
84 return EFI_UNSUPPORTED;\r
85 }\r
86 }\r
87 //\r
88 // Open the IO Abstraction(s) needed to perform the supported test\r
89 //\r
90 Status = gBS->OpenProtocol (\r
91 ControllerHandle,\r
92 &gEfiDevicePathProtocolGuid,\r
93 (VOID **) &ParentDevicePath,\r
94 This->DriverBindingHandle,\r
95 ControllerHandle,\r
96 EFI_OPEN_PROTOCOL_BY_DRIVER\r
97 );\r
98 if (Status == EFI_ALREADY_STARTED) {\r
99 return EFI_SUCCESS;\r
100 }\r
101\r
102 if (EFI_ERROR (Status)) {\r
103 return Status;\r
104 }\r
105 //\r
106 // Close the I/O Abstraction(s) used to perform the supported test\r
107 //\r
108 gBS->CloseProtocol (\r
109 ControllerHandle,\r
110 &gEfiDevicePathProtocolGuid,\r
111 This->DriverBindingHandle,\r
112 ControllerHandle\r
113 );\r
114\r
115 //\r
116 // Open the IO Abstraction(s) needed to perform the supported test\r
117 //\r
118 Status = gBS->OpenProtocol (\r
119 ControllerHandle,\r
120 &gEfiDiskIoProtocolGuid,\r
121 (VOID **) &DiskIo,\r
122 This->DriverBindingHandle,\r
123 ControllerHandle,\r
124 EFI_OPEN_PROTOCOL_BY_DRIVER\r
125 );\r
126 if (Status == EFI_ALREADY_STARTED) {\r
127 return EFI_SUCCESS;\r
128 }\r
129\r
130 if (EFI_ERROR (Status)) {\r
131 return Status;\r
132 }\r
133 //\r
134 // Close the I/O Abstraction(s) used to perform the supported test\r
135 //\r
136 gBS->CloseProtocol (\r
137 ControllerHandle,\r
138 &gEfiDiskIoProtocolGuid,\r
139 This->DriverBindingHandle,\r
140 ControllerHandle\r
141 );\r
142\r
143 //\r
144 // Open the IO Abstraction(s) needed to perform the supported test\r
145 //\r
146 Status = gBS->OpenProtocol (\r
147 ControllerHandle,\r
148 &gEfiBlockIoProtocolGuid,\r
149 NULL,\r
150 This->DriverBindingHandle,\r
151 ControllerHandle,\r
152 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
153 );\r
154\r
155 return Status;\r
156}\r
157\r
158EFI_STATUS\r
159EFIAPI\r
160PartitionDriverBindingStart (\r
161 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
162 IN EFI_HANDLE ControllerHandle,\r
163 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
164 )\r
165/*++\r
166\r
167 Routine Description:\r
168 Start this driver on ControllerHandle by opening a Block IO and Disk IO\r
169 protocol, reading Device Path, and creating a child handle with a\r
170 Disk IO and device path protocol.\r
171\r
172 Arguments:\r
173 This - Protocol instance pointer.\r
174 ControllerHandle - Handle of device to bind driver to\r
175 RemainingDevicePath - Not used\r
176\r
177 Returns:\r
178 EFI_SUCCESS - This driver is added to DeviceHandle\r
179 EFI_ALREADY_STARTED - This driver is already running on DeviceHandle\r
180 other - This driver does not support this device\r
181\r
182--*/\r
183{\r
184 EFI_STATUS Status;\r
185 EFI_STATUS OpenStatus;\r
186 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
187 EFI_DISK_IO_PROTOCOL *DiskIo;\r
188 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
c7c02fab 189 PARTITION_DETECT_ROUTINE *Routine;\r
878ddf1f 190\r
191 Status = gBS->OpenProtocol (\r
192 ControllerHandle,\r
193 &gEfiBlockIoProtocolGuid,\r
194 (VOID **) &BlockIo,\r
195 This->DriverBindingHandle,\r
196 ControllerHandle,\r
197 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
198 );\r
199 if (EFI_ERROR (Status)) {\r
200 return Status;\r
201 }\r
202 //\r
203 // Get the Device Path Protocol on ControllerHandle's handle\r
204 //\r
205 Status = gBS->OpenProtocol (\r
206 ControllerHandle,\r
207 &gEfiDevicePathProtocolGuid,\r
208 (VOID **) &ParentDevicePath,\r
209 This->DriverBindingHandle,\r
210 ControllerHandle,\r
211 EFI_OPEN_PROTOCOL_BY_DRIVER\r
212 );\r
213 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
214 return Status;\r
215 }\r
216\r
217 Status = gBS->OpenProtocol (\r
218 ControllerHandle,\r
219 &gEfiDiskIoProtocolGuid,\r
220 (VOID **) &DiskIo,\r
221 This->DriverBindingHandle,\r
222 ControllerHandle,\r
223 EFI_OPEN_PROTOCOL_BY_DRIVER\r
224 );\r
225 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
226 gBS->CloseProtocol (\r
227 ControllerHandle,\r
228 &gEfiDevicePathProtocolGuid,\r
229 This->DriverBindingHandle,\r
230 ControllerHandle\r
231 );\r
232 return Status;\r
233 }\r
234\r
235 OpenStatus = Status;\r
236\r
237 //\r
238 // If no media is present, do nothing here.\r
239 //\r
240 Status = EFI_UNSUPPORTED;\r
241 if (BlockIo->Media->MediaPresent) {\r
242 //\r
243 // Try for GPT, then El Torito, and then legacy MBR partition types. If the\r
244 // media supports a given partition type install child handles to represent\r
245 // the partitions described by the media.\r
246 //\r
c7c02fab 247 Routine = &mPartitionDetectRoutineTable[0];\r
248 while (*Routine != NULL) {\r
249 Status = (*Routine) (\r
250 This,\r
251 ControllerHandle,\r
252 DiskIo,\r
253 BlockIo,\r
254 ParentDevicePath\r
255 );\r
256 if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED) {\r
257 break;\r
258 }\r
259 Routine++;\r
878ddf1f 260 }\r
261 }\r
262 //\r
263 // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),\r
264 // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the\r
265 // driver. So don't try to close them. Otherwise, we will break the dependency\r
266 // between the controller and the driver set up before.\r
267 //\r
c7c02fab 268 if (EFI_ERROR (Status) && !EFI_ERROR (OpenStatus) && Status != EFI_MEDIA_CHANGED) {\r
878ddf1f 269 gBS->CloseProtocol (\r
270 ControllerHandle,\r
271 &gEfiDiskIoProtocolGuid,\r
272 This->DriverBindingHandle,\r
273 ControllerHandle\r
274 );\r
275\r
276 gBS->CloseProtocol (\r
277 ControllerHandle,\r
278 &gEfiDevicePathProtocolGuid,\r
279 This->DriverBindingHandle,\r
280 ControllerHandle\r
281 );\r
282 }\r
283\r
284 return Status;\r
285}\r
286\r
287EFI_STATUS\r
288EFIAPI\r
289PartitionDriverBindingStop (\r
290 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
291 IN EFI_HANDLE ControllerHandle,\r
292 IN UINTN NumberOfChildren,\r
293 IN EFI_HANDLE *ChildHandleBuffer\r
294 )\r
295/*++\r
296\r
297 Routine Description:\r
298 Stop this driver on ControllerHandle. Support stoping any child handles\r
299 created by this driver.\r
300\r
301 Arguments:\r
302 This - Protocol instance pointer.\r
303 ControllerHandle - Handle of device to stop driver on\r
304 NumberOfChildren - Number of Children in the ChildHandleBuffer\r
305 ChildHandleBuffer - List of handles for the children we need to stop.\r
306\r
307 Returns:\r
308 EFI_SUCCESS - This driver is removed DeviceHandle\r
309 EFI_DEVICE_ERROR - This driver was not removed from this device\r
310\r
311--*/\r
312{\r
313 EFI_STATUS Status;\r
314 UINTN Index;\r
315 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
316 BOOLEAN AllChildrenStopped;\r
317 PARTITION_PRIVATE_DATA *Private;\r
318 EFI_DISK_IO_PROTOCOL *DiskIo;\r
319\r
320 if (NumberOfChildren == 0) {\r
321 //\r
322 // Close the bus driver\r
323 //\r
324 gBS->CloseProtocol (\r
325 ControllerHandle,\r
326 &gEfiDiskIoProtocolGuid,\r
327 This->DriverBindingHandle,\r
328 ControllerHandle\r
329 );\r
330\r
331 gBS->CloseProtocol (\r
332 ControllerHandle,\r
333 &gEfiDevicePathProtocolGuid,\r
334 This->DriverBindingHandle,\r
335 ControllerHandle\r
336 );\r
337\r
338 return EFI_SUCCESS;\r
339 }\r
340\r
341 AllChildrenStopped = TRUE;\r
342 for (Index = 0; Index < NumberOfChildren; Index++) {\r
343 Status = gBS->OpenProtocol (\r
344 ChildHandleBuffer[Index],\r
345 &gEfiBlockIoProtocolGuid,\r
346 (VOID **) &BlockIo,\r
347 This->DriverBindingHandle,\r
348 ControllerHandle,\r
349 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
350 );\r
351 if (!EFI_ERROR (Status)) {\r
352\r
353 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);\r
354\r
355 //\r
356 // All Software protocols have be freed from the handle so remove it.\r
357 //\r
358 BlockIo->FlushBlocks (BlockIo);\r
359\r
360 Status = gBS->CloseProtocol (\r
361 ControllerHandle,\r
362 &gEfiDiskIoProtocolGuid,\r
363 This->DriverBindingHandle,\r
364 ChildHandleBuffer[Index]\r
365 );\r
366\r
367 Status = gBS->UninstallMultipleProtocolInterfaces (\r
368 ChildHandleBuffer[Index],\r
369 &gEfiDevicePathProtocolGuid,\r
370 Private->DevicePath,\r
371 &gEfiBlockIoProtocolGuid,\r
372 &Private->BlockIo,\r
373 Private->EspGuid,\r
374 NULL,\r
375 NULL\r
376 );\r
377 if (EFI_ERROR (Status)) {\r
378 gBS->OpenProtocol (\r
379 ControllerHandle,\r
380 &gEfiDiskIoProtocolGuid,\r
381 (VOID **) &DiskIo,\r
382 This->DriverBindingHandle,\r
383 ChildHandleBuffer[Index],\r
384 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
385 );\r
386 } else {\r
6626ad11
LG
387 FreePool (Private->DevicePath);\r
388 FreePool (Private);\r
878ddf1f 389 }\r
390\r
391 }\r
392\r
393 if (EFI_ERROR (Status)) {\r
394 AllChildrenStopped = FALSE;\r
395 }\r
396 }\r
397\r
398 if (!AllChildrenStopped) {\r
399 return EFI_DEVICE_ERROR;\r
400 }\r
401\r
402 return EFI_SUCCESS;\r
403}\r
404\r
1cc8ee78 405STATIC\r
878ddf1f 406EFI_STATUS\r
407EFIAPI\r
408PartitionReset (\r
409 IN EFI_BLOCK_IO_PROTOCOL *This,\r
410 IN BOOLEAN ExtendedVerification\r
411 )\r
412/*++\r
413\r
414 Routine Description:\r
415 Reset the parent Block Device.\r
416\r
417 Arguments:\r
418 This - Protocol instance pointer.\r
419 ExtendedVerification - Driver may perform diagnostics on reset.\r
420\r
421 Returns:\r
422 EFI_SUCCESS - The device was reset.\r
423 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
424 not be reset.\r
425\r
426--*/\r
427{\r
428 PARTITION_PRIVATE_DATA *Private;\r
429\r
430 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
431\r
432 return Private->ParentBlockIo->Reset (\r
433 Private->ParentBlockIo,\r
434 ExtendedVerification\r
435 );\r
436}\r
437\r
1cc8ee78 438STATIC\r
878ddf1f 439EFI_STATUS\r
440EFIAPI\r
441PartitionReadBlocks (\r
442 IN EFI_BLOCK_IO_PROTOCOL *This,\r
443 IN UINT32 MediaId,\r
444 IN EFI_LBA Lba,\r
445 IN UINTN BufferSize,\r
446 OUT VOID *Buffer\r
447 )\r
448/*++\r
449\r
450 Routine Description:\r
451 Read by using the Disk IO protocol on the parent device. Lba addresses\r
452 must be converted to byte offsets.\r
453\r
454 Arguments:\r
455 This - Protocol instance pointer.\r
456 MediaId - Id of the media, changes every time the media is replaced.\r
457 Lba - The starting Logical Block Address to read from\r
458 BufferSize - Size of Buffer, must be a multiple of device block size.\r
459 Buffer - Buffer containing read data\r
460\r
461 Returns:\r
462 EFI_SUCCESS - The data was read correctly from the device.\r
463 EFI_DEVICE_ERROR - The device reported an error while performing the read.\r
464 EFI_NO_MEDIA - There is no media in the device.\r
465 EFI_MEDIA_CHANGED - The MediaId does not matched the current device.\r
466 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the\r
467 device.\r
468 EFI_INVALID_PARAMETER - The read request contains device addresses that are not\r
469 valid for the device.\r
470\r
471--*/\r
472{\r
473 PARTITION_PRIVATE_DATA *Private;\r
474 UINT64 Offset;\r
475\r
476 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
477\r
478 if (BufferSize % Private->BlockSize != 0) {\r
479 return EFI_BAD_BUFFER_SIZE;\r
480 }\r
481\r
482 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
483 if (Offset + BufferSize > Private->End) {\r
484 return EFI_INVALID_PARAMETER;\r
485 }\r
486 //\r
487 // Because some kinds of partition have different block size from their parent\r
488 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
489 // protocol\r
490 //\r
491 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
492}\r
493\r
1cc8ee78 494STATIC\r
878ddf1f 495EFI_STATUS\r
496EFIAPI\r
497PartitionWriteBlocks (\r
498 IN EFI_BLOCK_IO_PROTOCOL *This,\r
499 IN UINT32 MediaId,\r
500 IN EFI_LBA Lba,\r
501 IN UINTN BufferSize,\r
502 OUT VOID *Buffer\r
503 )\r
504/*++\r
505\r
506 Routine Description:\r
507 Write by using the Disk IO protocol on the parent device. Lba addresses\r
508 must be converted to byte offsets.\r
509\r
510 Arguments:\r
511 This - Protocol instance pointer.\r
512 MediaId - Id of the media, changes every time the media is replaced.\r
513 Lba - The starting Logical Block Address to read from\r
514 BufferSize - Size of Buffer, must be a multiple of device block size.\r
515 Buffer - Buffer containing read data\r
516\r
517 Returns:\r
518 EFI_SUCCESS - The data was written correctly to the device.\r
519 EFI_WRITE_PROTECTED - The device can not be written to.\r
520 EFI_DEVICE_ERROR - The device reported an error while performing the write.\r
521 EFI_NO_MEDIA - There is no media in the device.\r
522 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.\r
523 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the\r
524 device.\r
525 EFI_INVALID_PARAMETER - The write request contains a LBA that is not\r
526 valid for the device.\r
527\r
528--*/\r
529{\r
530 PARTITION_PRIVATE_DATA *Private;\r
531 UINT64 Offset;\r
532\r
533 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
534\r
535 if (BufferSize % Private->BlockSize != 0) {\r
536 return EFI_BAD_BUFFER_SIZE;\r
537 }\r
538\r
539 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
540 if (Offset + BufferSize > Private->End) {\r
541 return EFI_INVALID_PARAMETER;\r
542 }\r
543 //\r
544 // Because some kinds of partition have different block size from their parent\r
545 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
546 // protocol\r
547 //\r
548 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
549}\r
550\r
1cc8ee78 551STATIC\r
878ddf1f 552EFI_STATUS\r
553EFIAPI\r
554PartitionFlushBlocks (\r
555 IN EFI_BLOCK_IO_PROTOCOL *This\r
556 )\r
557/*++\r
558\r
559 Routine Description:\r
560 Flush the parent Block Device.\r
561\r
562 Arguments:\r
563 This - Protocol instance pointer.\r
564\r
565 Returns:\r
566 EFI_SUCCESS - All outstanding data was written to the device\r
567 EFI_DEVICE_ERROR - The device reported an error while writing back the data\r
568 EFI_NO_MEDIA - There is no media in the device.\r
569\r
570--*/\r
571{\r
572 PARTITION_PRIVATE_DATA *Private;\r
573\r
574 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
575\r
576 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);\r
577}\r
578\r
579EFI_STATUS\r
580PartitionInstallChildHandle (\r
581 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
582 IN EFI_HANDLE ParentHandle,\r
583 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,\r
584 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,\r
585 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
586 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,\r
587 IN EFI_LBA Start,\r
588 IN EFI_LBA End,\r
589 IN UINT32 BlockSize,\r
590 IN BOOLEAN InstallEspGuid\r
591 )\r
592/*++\r
593\r
594Routine Description:\r
595 Create a child handle for a logical block device that represents the\r
596 bytes Start to End of the Parent Block IO device.\r
597\r
598Arguments:\r
599 This - Calling context.\r
600 ParentHandle - Parent Handle for new child\r
601 ParentDiskIo - Parent DiskIo interface\r
602 ParentBlockIo - Parent BlockIo interface\r
603 ParentDevicePath - Parent Device Path\r
604 DevicePathNode - Child Device Path node\r
605 Start - Start Block\r
606 End - End Block\r
607 BlockSize - Child block size\r
608 InstallEspGuid - Flag to install EFI System Partition GUID on handle\r
609\r
610Returns:\r
611 EFI_SUCCESS - If a child handle was added\r
612 EFI_OUT_OF_RESOURCES - A child handle was not added\r
613\r
614--*/\r
615{\r
616 EFI_STATUS Status;\r
617 PARTITION_PRIVATE_DATA *Private;\r
618\r
619 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));\r
620 if (Private == NULL) {\r
621 return EFI_OUT_OF_RESOURCES;\r
622 }\r
623\r
624 Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;\r
625\r
626 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);\r
627 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);\r
628\r
629 Private->BlockSize = BlockSize;\r
630 Private->ParentBlockIo = ParentBlockIo;\r
631 Private->DiskIo = ParentDiskIo;\r
632\r
633 Private->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
634\r
635 Private->BlockIo.Media = &Private->Media;\r
636 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
637 Private->Media.LogicalPartition = TRUE;\r
638 Private->Media.LastBlock = DivU64x32 (\r
639 MultU64x32 (\r
640 End - Start + 1,\r
641 ParentBlockIo->Media->BlockSize\r
642 ),\r
643 BlockSize\r
644 ) - 1;\r
645\r
646 Private->Media.BlockSize = (UINT32) BlockSize;\r
647\r
648 Private->BlockIo.Reset = PartitionReset;\r
649 Private->BlockIo.ReadBlocks = PartitionReadBlocks;\r
650 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;\r
651 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;\r
652\r
653 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);\r
654\r
655 if (Private->DevicePath == NULL) {\r
6626ad11 656 FreePool (Private);\r
878ddf1f 657 return EFI_OUT_OF_RESOURCES;\r
658 }\r
659\r
660 if (InstallEspGuid) {\r
661 Private->EspGuid = &gEfiPartTypeSystemPartGuid;\r
662 } else {\r
663 //\r
664 // If NULL InstallMultipleProtocolInterfaces will ignore it.\r
665 //\r
666 Private->EspGuid = NULL;\r
667 }\r
668 //\r
669 // Create the new handle\r
670 //\r
671 Private->Handle = NULL;\r
672 Status = gBS->InstallMultipleProtocolInterfaces (\r
673 &Private->Handle,\r
674 &gEfiDevicePathProtocolGuid,\r
675 Private->DevicePath,\r
676 &gEfiBlockIoProtocolGuid,\r
677 &Private->BlockIo,\r
678 Private->EspGuid,\r
679 NULL,\r
680 NULL\r
681 );\r
682\r
683 if (!EFI_ERROR (Status)) {\r
684 //\r
685 // Open the Parent Handle for the child\r
686 //\r
687 Status = gBS->OpenProtocol (\r
688 ParentHandle,\r
689 &gEfiDiskIoProtocolGuid,\r
690 (VOID **) &ParentDiskIo,\r
691 This->DriverBindingHandle,\r
692 Private->Handle,\r
693 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
694 );\r
695 } else {\r
6626ad11
LG
696 FreePool (Private->DevicePath);\r
697 FreePool (Private);\r
878ddf1f 698 }\r
699\r
700 return Status;\r
701}\r