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