]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c
Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[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
1cc8ee78 440STATIC\r
878ddf1f 441EFI_STATUS\r
442EFIAPI\r
443PartitionReset (\r
444 IN EFI_BLOCK_IO_PROTOCOL *This,\r
445 IN BOOLEAN ExtendedVerification\r
446 )\r
447/*++\r
448\r
449 Routine Description:\r
450 Reset the parent Block Device.\r
451\r
452 Arguments:\r
453 This - Protocol instance pointer.\r
454 ExtendedVerification - Driver may perform diagnostics on reset.\r
455\r
456 Returns:\r
457 EFI_SUCCESS - The device was reset.\r
458 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
459 not be reset.\r
460\r
461--*/\r
462{\r
463 PARTITION_PRIVATE_DATA *Private;\r
464\r
465 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
466\r
467 return Private->ParentBlockIo->Reset (\r
468 Private->ParentBlockIo,\r
469 ExtendedVerification\r
470 );\r
471}\r
472\r
1cc8ee78 473STATIC\r
878ddf1f 474EFI_STATUS\r
475EFIAPI\r
476PartitionReadBlocks (\r
477 IN EFI_BLOCK_IO_PROTOCOL *This,\r
478 IN UINT32 MediaId,\r
479 IN EFI_LBA Lba,\r
480 IN UINTN BufferSize,\r
481 OUT VOID *Buffer\r
482 )\r
483/*++\r
484\r
485 Routine Description:\r
486 Read by using the Disk IO protocol on the parent device. Lba addresses\r
487 must be converted to byte offsets.\r
488\r
489 Arguments:\r
490 This - Protocol instance pointer.\r
491 MediaId - Id of the media, changes every time the media is replaced.\r
492 Lba - The starting Logical Block Address to read from\r
493 BufferSize - Size of Buffer, must be a multiple of device block size.\r
494 Buffer - Buffer containing read data\r
495\r
496 Returns:\r
497 EFI_SUCCESS - The data was read correctly from the device.\r
498 EFI_DEVICE_ERROR - The device reported an error while performing the read.\r
499 EFI_NO_MEDIA - There is no media in the device.\r
500 EFI_MEDIA_CHANGED - The MediaId does not matched the current device.\r
501 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the\r
502 device.\r
503 EFI_INVALID_PARAMETER - The read request contains device addresses that are not\r
504 valid for the device.\r
505\r
506--*/\r
507{\r
508 PARTITION_PRIVATE_DATA *Private;\r
509 UINT64 Offset;\r
510\r
511 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
512\r
513 if (BufferSize % Private->BlockSize != 0) {\r
514 return EFI_BAD_BUFFER_SIZE;\r
515 }\r
516\r
517 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
518 if (Offset + BufferSize > Private->End) {\r
519 return EFI_INVALID_PARAMETER;\r
520 }\r
521 //\r
522 // Because some kinds of partition have different block size from their parent\r
523 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
524 // protocol\r
525 //\r
526 return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
527}\r
528\r
1cc8ee78 529STATIC\r
878ddf1f 530EFI_STATUS\r
531EFIAPI\r
532PartitionWriteBlocks (\r
533 IN EFI_BLOCK_IO_PROTOCOL *This,\r
534 IN UINT32 MediaId,\r
535 IN EFI_LBA Lba,\r
536 IN UINTN BufferSize,\r
537 OUT VOID *Buffer\r
538 )\r
539/*++\r
540\r
541 Routine Description:\r
542 Write by using the Disk IO protocol on the parent device. Lba addresses\r
543 must be converted to byte offsets.\r
544\r
545 Arguments:\r
546 This - Protocol instance pointer.\r
547 MediaId - Id of the media, changes every time the media is replaced.\r
548 Lba - The starting Logical Block Address to read from\r
549 BufferSize - Size of Buffer, must be a multiple of device block size.\r
550 Buffer - Buffer containing read data\r
551\r
552 Returns:\r
553 EFI_SUCCESS - The data was written correctly to the device.\r
554 EFI_WRITE_PROTECTED - The device can not be written to.\r
555 EFI_DEVICE_ERROR - The device reported an error while performing the write.\r
556 EFI_NO_MEDIA - There is no media in the device.\r
557 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.\r
558 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the\r
559 device.\r
560 EFI_INVALID_PARAMETER - The write request contains a LBA that is not\r
561 valid for the device.\r
562\r
563--*/\r
564{\r
565 PARTITION_PRIVATE_DATA *Private;\r
566 UINT64 Offset;\r
567\r
568 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
569\r
570 if (BufferSize % Private->BlockSize != 0) {\r
571 return EFI_BAD_BUFFER_SIZE;\r
572 }\r
573\r
574 Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
575 if (Offset + BufferSize > Private->End) {\r
576 return EFI_INVALID_PARAMETER;\r
577 }\r
578 //\r
579 // Because some kinds of partition have different block size from their parent\r
580 // device, we call the Disk IO protocol on the parent device, not the Block IO\r
581 // protocol\r
582 //\r
583 return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);\r
584}\r
585\r
1cc8ee78 586STATIC\r
878ddf1f 587EFI_STATUS\r
588EFIAPI\r
589PartitionFlushBlocks (\r
590 IN EFI_BLOCK_IO_PROTOCOL *This\r
591 )\r
592/*++\r
593\r
594 Routine Description:\r
595 Flush the parent Block Device.\r
596\r
597 Arguments:\r
598 This - Protocol instance pointer.\r
599\r
600 Returns:\r
601 EFI_SUCCESS - All outstanding data was written to the device\r
602 EFI_DEVICE_ERROR - The device reported an error while writing back the data\r
603 EFI_NO_MEDIA - There is no media in the device.\r
604\r
605--*/\r
606{\r
607 PARTITION_PRIVATE_DATA *Private;\r
608\r
609 Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);\r
610\r
611 return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);\r
612}\r
613\r
614EFI_STATUS\r
615PartitionInstallChildHandle (\r
616 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
617 IN EFI_HANDLE ParentHandle,\r
618 IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,\r
619 IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,\r
620 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
621 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,\r
622 IN EFI_LBA Start,\r
623 IN EFI_LBA End,\r
624 IN UINT32 BlockSize,\r
625 IN BOOLEAN InstallEspGuid\r
626 )\r
627/*++\r
628\r
629Routine Description:\r
630 Create a child handle for a logical block device that represents the\r
631 bytes Start to End of the Parent Block IO device.\r
632\r
633Arguments:\r
634 This - Calling context.\r
635 ParentHandle - Parent Handle for new child\r
636 ParentDiskIo - Parent DiskIo interface\r
637 ParentBlockIo - Parent BlockIo interface\r
638 ParentDevicePath - Parent Device Path\r
639 DevicePathNode - Child Device Path node\r
640 Start - Start Block\r
641 End - End Block\r
642 BlockSize - Child block size\r
643 InstallEspGuid - Flag to install EFI System Partition GUID on handle\r
644\r
645Returns:\r
646 EFI_SUCCESS - If a child handle was added\r
647 EFI_OUT_OF_RESOURCES - A child handle was not added\r
648\r
649--*/\r
650{\r
651 EFI_STATUS Status;\r
652 PARTITION_PRIVATE_DATA *Private;\r
653\r
654 Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));\r
655 if (Private == NULL) {\r
656 return EFI_OUT_OF_RESOURCES;\r
657 }\r
658\r
659 Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;\r
660\r
661 Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);\r
662 Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);\r
663\r
664 Private->BlockSize = BlockSize;\r
665 Private->ParentBlockIo = ParentBlockIo;\r
666 Private->DiskIo = ParentDiskIo;\r
667\r
668 Private->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
669\r
670 Private->BlockIo.Media = &Private->Media;\r
671 CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
672 Private->Media.LogicalPartition = TRUE;\r
673 Private->Media.LastBlock = DivU64x32 (\r
674 MultU64x32 (\r
675 End - Start + 1,\r
676 ParentBlockIo->Media->BlockSize\r
677 ),\r
678 BlockSize\r
679 ) - 1;\r
680\r
681 Private->Media.BlockSize = (UINT32) BlockSize;\r
682\r
683 Private->BlockIo.Reset = PartitionReset;\r
684 Private->BlockIo.ReadBlocks = PartitionReadBlocks;\r
685 Private->BlockIo.WriteBlocks = PartitionWriteBlocks;\r
686 Private->BlockIo.FlushBlocks = PartitionFlushBlocks;\r
687\r
688 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);\r
689\r
690 if (Private->DevicePath == NULL) {\r
691 gBS->FreePool (Private);\r
692 return EFI_OUT_OF_RESOURCES;\r
693 }\r
694\r
695 if (InstallEspGuid) {\r
696 Private->EspGuid = &gEfiPartTypeSystemPartGuid;\r
697 } else {\r
698 //\r
699 // If NULL InstallMultipleProtocolInterfaces will ignore it.\r
700 //\r
701 Private->EspGuid = NULL;\r
702 }\r
703 //\r
704 // Create the new handle\r
705 //\r
706 Private->Handle = NULL;\r
707 Status = gBS->InstallMultipleProtocolInterfaces (\r
708 &Private->Handle,\r
709 &gEfiDevicePathProtocolGuid,\r
710 Private->DevicePath,\r
711 &gEfiBlockIoProtocolGuid,\r
712 &Private->BlockIo,\r
713 Private->EspGuid,\r
714 NULL,\r
715 NULL\r
716 );\r
717\r
718 if (!EFI_ERROR (Status)) {\r
719 //\r
720 // Open the Parent Handle for the child\r
721 //\r
722 Status = gBS->OpenProtocol (\r
723 ParentHandle,\r
724 &gEfiDiskIoProtocolGuid,\r
725 (VOID **) &ParentDiskIo,\r
726 This->DriverBindingHandle,\r
727 Private->Handle,\r
728 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
729 );\r
730 } else {\r
731 gBS->FreePool (Private->DevicePath);\r
732 gBS->FreePool (Private);\r
733 }\r
734\r
735 return Status;\r
736}\r