]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
Code scrub for DiskIo, Partition & Unicode Collation
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / DiskIoDxe / DiskIo.c
CommitLineData
adbcbf8f 1/** @file\r
ff61847d 2 DiskIo driver that lays on every BlockIo protocol in the system.\r
adbcbf8f 3 DiskIo converts a block oriented device to a byte oriented device.\r
4\r
ff61847d 5 Disk access may have to handle unaligned request about sector boundaries.\r
adbcbf8f 6 There are three cases:\r
7 UnderRun - The first byte is not on a sector boundary or the read request is\r
8 less than a sector in length.\r
9 Aligned - A read of N contiguous sectors.\r
10 OverRun - The last byte is not on a sector boundary.\r
11\r
f42be642 12Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
13All rights reserved. This program and the accompanying materials\r
14are licensed and made available under the terms and conditions of the BSD License\r
15which accompanies this distribution. The full text of the license may be found at\r
16http://opensource.org/licenses/bsd-license.php\r
17\r
18THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
19WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
adbcbf8f 20\r
21**/\r
22\r
23#include "DiskIo.h"\r
24\r
ff61847d 25//\r
26// Driver binding protocol implementation for DiskIo driver.\r
27//\r
adbcbf8f 28EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding = {\r
29 DiskIoDriverBindingSupported,\r
30 DiskIoDriverBindingStart,\r
31 DiskIoDriverBindingStop,\r
32 0xa,\r
33 NULL,\r
34 NULL\r
35};\r
36\r
ff61847d 37//\r
38// Template for DiskIo private data structure.\r
39// The pointer to BlockIo protocol interface is assigned dynamically.\r
40//\r
adbcbf8f 41DISK_IO_PRIVATE_DATA gDiskIoPrivateDataTemplate = {\r
42 DISK_IO_PRIVATE_DATA_SIGNATURE,\r
43 {\r
44 EFI_DISK_IO_PROTOCOL_REVISION,\r
45 DiskIoReadDisk,\r
46 DiskIoWriteDisk\r
47 },\r
48 NULL\r
49};\r
50\r
51\r
52/**\r
53 Test to see if this driver supports ControllerHandle. \r
54\r
55 @param This Protocol instance pointer.\r
56 @param ControllerHandle Handle of device to test\r
57 @param RemainingDevicePath Optional parameter use to pick a specific child\r
58 device to start.\r
59\r
60 @retval EFI_SUCCESS This driver supports this device\r
61 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
62 @retval other This driver does not support this device\r
63\r
64**/\r
65EFI_STATUS\r
66EFIAPI\r
67DiskIoDriverBindingSupported (\r
68 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
69 IN EFI_HANDLE ControllerHandle,\r
70 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
71 )\r
72{\r
73 EFI_STATUS Status;\r
74 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
75\r
76 //\r
77 // Open the IO Abstraction(s) needed to perform the supported test.\r
78 //\r
79 Status = gBS->OpenProtocol (\r
80 ControllerHandle,\r
81 &gEfiBlockIoProtocolGuid,\r
82 (VOID **) &BlockIo,\r
83 This->DriverBindingHandle,\r
84 ControllerHandle,\r
85 EFI_OPEN_PROTOCOL_BY_DRIVER\r
86 );\r
87 if (EFI_ERROR (Status)) {\r
88 return Status;\r
89 }\r
90\r
91 //\r
92 // Close the I/O Abstraction(s) used to perform the supported test.\r
93 //\r
94 gBS->CloseProtocol (\r
95 ControllerHandle,\r
96 &gEfiBlockIoProtocolGuid,\r
97 This->DriverBindingHandle,\r
98 ControllerHandle\r
99 );\r
100 return EFI_SUCCESS;\r
101}\r
102\r
103\r
104/**\r
105 Start this driver on ControllerHandle by opening a Block IO protocol and\r
106 installing a Disk IO protocol on ControllerHandle.\r
107\r
108 @param This Protocol instance pointer.\r
109 @param ControllerHandle Handle of device to bind driver to\r
110 @param RemainingDevicePath Optional parameter use to pick a specific child\r
111 device to start.\r
112\r
113 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
114 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
115 @retval other This driver does not support this device\r
116\r
117**/\r
118EFI_STATUS\r
119EFIAPI\r
120DiskIoDriverBindingStart (\r
121 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
122 IN EFI_HANDLE ControllerHandle,\r
123 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
124 )\r
125{\r
126 EFI_STATUS Status;\r
127 DISK_IO_PRIVATE_DATA *Private;\r
128\r
129 Private = NULL;\r
130\r
131 //\r
132 // Connect to the Block IO interface on ControllerHandle.\r
133 //\r
134 Status = gBS->OpenProtocol (\r
135 ControllerHandle,\r
136 &gEfiBlockIoProtocolGuid,\r
137 (VOID **) &gDiskIoPrivateDataTemplate.BlockIo,\r
138 This->DriverBindingHandle,\r
139 ControllerHandle,\r
140 EFI_OPEN_PROTOCOL_BY_DRIVER\r
141 );\r
142 if (EFI_ERROR (Status)) {\r
143 return Status;\r
144 }\r
145 \r
146 //\r
147 // Initialize the Disk IO device instance.\r
148 //\r
149 Private = AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA), &gDiskIoPrivateDataTemplate);\r
150 if (Private == NULL) {\r
151 Status = EFI_OUT_OF_RESOURCES;\r
152 goto ErrorExit;\r
153 }\r
154 \r
155 //\r
156 // Install protocol interfaces for the Disk IO device.\r
157 //\r
158 Status = gBS->InstallProtocolInterface (\r
159 &ControllerHandle,\r
160 &gEfiDiskIoProtocolGuid,\r
161 EFI_NATIVE_INTERFACE,\r
162 &Private->DiskIo\r
163 );\r
164\r
165ErrorExit:\r
166 if (EFI_ERROR (Status)) {\r
167\r
168 if (Private != NULL) {\r
169 FreePool (Private);\r
170 }\r
171\r
172 gBS->CloseProtocol (\r
173 ControllerHandle,\r
174 &gEfiBlockIoProtocolGuid,\r
175 This->DriverBindingHandle,\r
176 ControllerHandle\r
177 );\r
178 }\r
179\r
180 return Status;\r
181}\r
182\r
183\r
184/**\r
185 Stop this driver on ControllerHandle by removing Disk IO protocol and closing\r
186 the Block IO protocol on ControllerHandle.\r
187\r
188 @param This Protocol instance pointer.\r
189 @param ControllerHandle Handle of device to stop driver on\r
190 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
191 children is zero stop the entire bus driver.\r
192 @param ChildHandleBuffer List of Child Handles to Stop.\r
193\r
194 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
195 @retval other This driver was not removed from this device\r
196\r
197**/\r
198EFI_STATUS\r
199EFIAPI\r
200DiskIoDriverBindingStop (\r
201 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
202 IN EFI_HANDLE ControllerHandle,\r
203 IN UINTN NumberOfChildren,\r
204 IN EFI_HANDLE *ChildHandleBuffer\r
205 )\r
206{\r
207 EFI_STATUS Status;\r
208 EFI_DISK_IO_PROTOCOL *DiskIo;\r
209 DISK_IO_PRIVATE_DATA *Private;\r
210\r
211 //\r
212 // Get our context back.\r
213 //\r
214 Status = gBS->OpenProtocol (\r
215 ControllerHandle,\r
216 &gEfiDiskIoProtocolGuid,\r
217 (VOID **) &DiskIo,\r
218 This->DriverBindingHandle,\r
219 ControllerHandle,\r
220 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
221 );\r
222 if (EFI_ERROR (Status)) {\r
223 return EFI_UNSUPPORTED;\r
224 }\r
225\r
226 Private = DISK_IO_PRIVATE_DATA_FROM_THIS (DiskIo);\r
227\r
228 Status = gBS->UninstallProtocolInterface (\r
229 ControllerHandle,\r
230 &gEfiDiskIoProtocolGuid,\r
231 &Private->DiskIo\r
232 );\r
233 if (!EFI_ERROR (Status)) {\r
234\r
235 Status = gBS->CloseProtocol (\r
236 ControllerHandle,\r
237 &gEfiBlockIoProtocolGuid,\r
238 This->DriverBindingHandle,\r
239 ControllerHandle\r
240 );\r
241 }\r
242\r
243 if (!EFI_ERROR (Status)) {\r
244 FreePool (Private);\r
245 }\r
246\r
247 return Status;\r
248}\r
249\r
250\r
251\r
252/**\r
253 Read BufferSize bytes from Offset into Buffer.\r
254 Reads may support reads that are not aligned on\r
255 sector boundaries. There are three cases:\r
256 UnderRun - The first byte is not on a sector boundary or the read request is\r
257 less than a sector in length.\r
258 Aligned - A read of N contiguous sectors.\r
259 OverRun - The last byte is not on a sector boundary.\r
260\r
261 @param This Protocol instance pointer.\r
262 @param MediaId Id of the media, changes every time the media is replaced.\r
263 @param Offset The starting byte offset to read from\r
264 @param BufferSize Size of Buffer\r
265 @param Buffer Buffer containing read data\r
266\r
267 @retval EFI_SUCCESS The data was read correctly from the device.\r
268 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
269 @retval EFI_NO_MEDIA There is no media in the device.\r
270 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
271 @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not\r
272 valid for the device.\r
273\r
274**/\r
275EFI_STATUS\r
276EFIAPI\r
277DiskIoReadDisk (\r
278 IN EFI_DISK_IO_PROTOCOL *This,\r
279 IN UINT32 MediaId,\r
280 IN UINT64 Offset,\r
281 IN UINTN BufferSize,\r
282 OUT VOID *Buffer\r
283 )\r
284{\r
285 EFI_STATUS Status;\r
286 DISK_IO_PRIVATE_DATA *Private;\r
287 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
288 EFI_BLOCK_IO_MEDIA *Media;\r
289 UINT32 BlockSize;\r
290 UINT64 Lba;\r
291 UINT64 OverRunLba;\r
292 UINT32 UnderRun;\r
293 UINT32 OverRun;\r
294 BOOLEAN TransactionComplete;\r
295 UINTN WorkingBufferSize;\r
296 UINT8 *WorkingBuffer;\r
297 UINTN Length;\r
298 UINT8 *Data;\r
299 UINT8 *PreData;\r
300 UINTN IsBufferAligned;\r
301 UINTN DataBufferSize;\r
302 BOOLEAN LastRead;\r
303\r
304 Private = DISK_IO_PRIVATE_DATA_FROM_THIS (This);\r
305\r
306 BlockIo = Private->BlockIo;\r
307 Media = BlockIo->Media;\r
308 BlockSize = Media->BlockSize;\r
309\r
310 if (Media->MediaId != MediaId) {\r
311 return EFI_MEDIA_CHANGED;\r
312 }\r
313\r
314 WorkingBuffer = Buffer;\r
315 WorkingBufferSize = BufferSize;\r
316\r
317 //\r
318 // Allocate a temporary buffer for operation\r
319 //\r
320 DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM;\r
321\r
322 if (Media->IoAlign > 1) {\r
323 PreData = AllocatePool (DataBufferSize + Media->IoAlign);\r
324 Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign;\r
325 } else {\r
326 PreData = AllocatePool (DataBufferSize);\r
327 Data = PreData;\r
328 }\r
329\r
330 if (PreData == NULL) {\r
331 return EFI_OUT_OF_RESOURCES;\r
332 }\r
333\r
334 Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun);\r
335\r
336 Length = BlockSize - UnderRun;\r
337 TransactionComplete = FALSE;\r
338\r
339 Status = EFI_SUCCESS;\r
340 if (UnderRun != 0) {\r
341 //\r
342 // Offset starts in the middle of an Lba, so read the entire block.\r
343 //\r
344 Status = BlockIo->ReadBlocks (\r
345 BlockIo,\r
346 MediaId,\r
347 Lba,\r
348 BlockSize,\r
349 Data\r
350 );\r
351\r
352 if (EFI_ERROR (Status)) {\r
353 goto Done;\r
354 }\r
355\r
356 if (Length > BufferSize) {\r
357 Length = BufferSize;\r
358 TransactionComplete = TRUE;\r
359 }\r
360\r
361 CopyMem (WorkingBuffer, Data + UnderRun, Length);\r
362\r
363 WorkingBuffer += Length;\r
364\r
365 WorkingBufferSize -= Length;\r
366 if (WorkingBufferSize == 0) {\r
367 goto Done;\r
368 }\r
369\r
370 Lba += 1;\r
371 }\r
372\r
373 OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun);\r
374\r
375 if (!TransactionComplete && WorkingBufferSize >= BlockSize) {\r
376 //\r
377 // If the DiskIo maps directly to a BlockIo device do the read.\r
378 //\r
379 if (OverRun != 0) {\r
380 WorkingBufferSize -= OverRun;\r
381 }\r
382 //\r
383 // Check buffer alignment\r
384 //\r
385 IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1);\r
386\r
387 if (Media->IoAlign <= 1 || IsBufferAligned == 0) {\r
388 //\r
389 // Alignment is satisfied, so read them together\r
390 //\r
391 Status = BlockIo->ReadBlocks (\r
392 BlockIo,\r
393 MediaId,\r
394 Lba,\r
395 WorkingBufferSize,\r
396 WorkingBuffer\r
397 );\r
398\r
399 if (EFI_ERROR (Status)) {\r
400 goto Done;\r
401 }\r
402\r
403 WorkingBuffer += WorkingBufferSize;\r
404\r
405 } else {\r
406 //\r
407 // Use the allocated buffer instead of the original buffer\r
408 // to avoid alignment issue.\r
409 // Here, the allocated buffer (8-byte align) can satisfy the alignment\r
410 //\r
411 LastRead = FALSE;\r
412 do {\r
413 if (WorkingBufferSize <= DataBufferSize) {\r
414 //\r
415 // It is the last calling to readblocks in this loop\r
416 //\r
417 DataBufferSize = WorkingBufferSize;\r
418 LastRead = TRUE;\r
419 }\r
420\r
421 Status = BlockIo->ReadBlocks (\r
422 BlockIo,\r
423 MediaId,\r
424 Lba,\r
425 DataBufferSize,\r
426 Data\r
427 );\r
428 if (EFI_ERROR (Status)) {\r
429 goto Done;\r
430 }\r
431\r
432 CopyMem (WorkingBuffer, Data, DataBufferSize);\r
433 WorkingBufferSize -= DataBufferSize;\r
434 WorkingBuffer += DataBufferSize;\r
435 Lba += DATA_BUFFER_BLOCK_NUM;\r
436 } while (!LastRead);\r
437 }\r
438 }\r
439\r
440 if (!TransactionComplete && OverRun != 0) {\r
441 //\r
442 // Last read is not a complete block.\r
443 //\r
444 Status = BlockIo->ReadBlocks (\r
445 BlockIo,\r
446 MediaId,\r
447 OverRunLba,\r
448 BlockSize,\r
449 Data\r
450 );\r
451\r
452 if (EFI_ERROR (Status)) {\r
453 goto Done;\r
454 }\r
455\r
456 CopyMem (WorkingBuffer, Data, OverRun);\r
457 }\r
458\r
459Done:\r
460 if (PreData != NULL) {\r
461 FreePool (PreData);\r
462 }\r
463\r
464 return Status;\r
465}\r
466\r
467\r
468/**\r
ff61847d 469 Writes BufferSize bytes from Buffer into Offset.\r
adbcbf8f 470 Writes may require a read modify write to support writes that are not\r
471 aligned on sector boundaries. There are three cases:\r
472 UnderRun - The first byte is not on a sector boundary or the write request\r
473 is less than a sector in length. Read modify write is required.\r
474 Aligned - A write of N contiguous sectors.\r
475 OverRun - The last byte is not on a sector boundary. Read modified write\r
476 required.\r
477\r
478 @param This Protocol instance pointer.\r
479 @param MediaId Id of the media, changes every time the media is replaced.\r
480 @param Offset The starting byte offset to read from\r
481 @param BufferSize Size of Buffer\r
482 @param Buffer Buffer containing read data\r
483\r
484 @retval EFI_SUCCESS The data was written correctly to the device.\r
485 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
486 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
487 @retval EFI_NO_MEDIA There is no media in the device.\r
488 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
489 @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not\r
490 valid for the device.\r
491\r
492**/\r
493EFI_STATUS\r
494EFIAPI\r
495DiskIoWriteDisk (\r
496 IN EFI_DISK_IO_PROTOCOL *This,\r
497 IN UINT32 MediaId,\r
498 IN UINT64 Offset,\r
499 IN UINTN BufferSize,\r
500 IN VOID *Buffer\r
501 )\r
502{\r
503 EFI_STATUS Status;\r
504 DISK_IO_PRIVATE_DATA *Private;\r
505 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
506 EFI_BLOCK_IO_MEDIA *Media;\r
507 UINT32 BlockSize;\r
508 UINT64 Lba;\r
509 UINT64 OverRunLba;\r
510 UINT32 UnderRun;\r
511 UINT32 OverRun;\r
512 BOOLEAN TransactionComplete;\r
513 UINTN WorkingBufferSize;\r
514 UINT8 *WorkingBuffer;\r
515 UINTN Length;\r
516 UINT8 *Data;\r
517 UINT8 *PreData;\r
518 UINTN IsBufferAligned;\r
519 UINTN DataBufferSize;\r
520 BOOLEAN LastWrite;\r
521\r
522 Private = DISK_IO_PRIVATE_DATA_FROM_THIS (This);\r
523\r
524 BlockIo = Private->BlockIo;\r
525 Media = BlockIo->Media;\r
526 BlockSize = Media->BlockSize;\r
527\r
528 if (Media->ReadOnly) {\r
529 return EFI_WRITE_PROTECTED;\r
530 }\r
531\r
532 if (Media->MediaId != MediaId) {\r
533 return EFI_MEDIA_CHANGED;\r
534 }\r
535\r
536 DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM;\r
537\r
538 if (Media->IoAlign > 1) {\r
539 PreData = AllocatePool (DataBufferSize + Media->IoAlign);\r
540 Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign;\r
541 } else {\r
542 PreData = AllocatePool (DataBufferSize);\r
543 Data = PreData;\r
544 }\r
545\r
546 if (PreData == NULL) {\r
547 return EFI_OUT_OF_RESOURCES;\r
548 }\r
549\r
550 WorkingBuffer = Buffer;\r
551 WorkingBufferSize = BufferSize;\r
552\r
553 Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun);\r
554\r
555 Length = BlockSize - UnderRun;\r
556 TransactionComplete = FALSE;\r
557\r
558 Status = EFI_SUCCESS;\r
559 if (UnderRun != 0) {\r
560 //\r
561 // Offset starts in the middle of an Lba, so do read modify write.\r
562 //\r
563 Status = BlockIo->ReadBlocks (\r
564 BlockIo,\r
565 MediaId,\r
566 Lba,\r
567 BlockSize,\r
568 Data\r
569 );\r
570\r
571 if (EFI_ERROR (Status)) {\r
572 goto Done;\r
573 }\r
574\r
575 if (Length > BufferSize) {\r
576 Length = BufferSize;\r
577 TransactionComplete = TRUE;\r
578 }\r
579\r
580 CopyMem (Data + UnderRun, WorkingBuffer, Length);\r
581\r
582 Status = BlockIo->WriteBlocks (\r
583 BlockIo,\r
584 MediaId,\r
585 Lba,\r
586 BlockSize,\r
587 Data\r
588 );\r
589 if (EFI_ERROR (Status)) {\r
590 goto Done;\r
591 }\r
592\r
593 WorkingBuffer += Length;\r
594 WorkingBufferSize -= Length;\r
595 if (WorkingBufferSize == 0) {\r
596 goto Done;\r
597 }\r
598\r
599 Lba += 1;\r
600 }\r
601\r
602 OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun);\r
603\r
604 if (!TransactionComplete && WorkingBufferSize >= BlockSize) {\r
605 //\r
606 // If the DiskIo maps directly to a BlockIo device do the write.\r
607 //\r
608 if (OverRun != 0) {\r
609 WorkingBufferSize -= OverRun;\r
610 }\r
611 //\r
612 // Check buffer alignment\r
613 //\r
614 IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1);\r
615\r
616 if (Media->IoAlign <= 1 || IsBufferAligned == 0) {\r
617 //\r
618 // Alignment is satisfied, so write them together\r
619 //\r
620 Status = BlockIo->WriteBlocks (\r
621 BlockIo,\r
622 MediaId,\r
623 Lba,\r
624 WorkingBufferSize,\r
625 WorkingBuffer\r
626 );\r
627\r
628 if (EFI_ERROR (Status)) {\r
629 goto Done;\r
630 }\r
631\r
632 WorkingBuffer += WorkingBufferSize;\r
633\r
634 } else {\r
635 //\r
636 // The buffer parameter is not aligned with the request\r
637 // So use the allocated instead.\r
638 // It can fit almost all the cases.\r
639 //\r
640 LastWrite = FALSE;\r
641 do {\r
642 if (WorkingBufferSize <= DataBufferSize) {\r
643 //\r
644 // It is the last calling to writeblocks in this loop\r
645 //\r
646 DataBufferSize = WorkingBufferSize;\r
647 LastWrite = TRUE;\r
648 }\r
649\r
650 CopyMem (Data, WorkingBuffer, DataBufferSize);\r
651 Status = BlockIo->WriteBlocks (\r
652 BlockIo,\r
653 MediaId,\r
654 Lba,\r
655 DataBufferSize,\r
656 Data\r
657 );\r
658 if (EFI_ERROR (Status)) {\r
659 goto Done;\r
660 }\r
661\r
662 WorkingBufferSize -= DataBufferSize;\r
663 WorkingBuffer += DataBufferSize;\r
664 Lba += DATA_BUFFER_BLOCK_NUM;\r
665 } while (!LastWrite);\r
666 }\r
667 }\r
668\r
669 if (!TransactionComplete && OverRun != 0) {\r
670 //\r
671 // Last bit is not a complete block, so do a read modify write.\r
672 //\r
673 Status = BlockIo->ReadBlocks (\r
674 BlockIo,\r
675 MediaId,\r
676 OverRunLba,\r
677 BlockSize,\r
678 Data\r
679 );\r
680\r
681 if (EFI_ERROR (Status)) {\r
682 goto Done;\r
683 }\r
684\r
685 CopyMem (Data, WorkingBuffer, OverRun);\r
686\r
687 Status = BlockIo->WriteBlocks (\r
688 BlockIo,\r
689 MediaId,\r
690 OverRunLba,\r
691 BlockSize,\r
692 Data\r
693 );\r
694 if (EFI_ERROR (Status)) {\r
695 goto Done;\r
696 }\r
697 }\r
698\r
699Done:\r
700 if (PreData != NULL) {\r
701 FreePool (PreData);\r
702 }\r
703\r
704 return Status;\r
705}\r
706\r
707\r
708/**\r
709 The user Entry Point for module DiskIo. The user code starts with this function.\r
710\r
711 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
712 @param[in] SystemTable A pointer to the EFI System Table.\r
713 \r
714 @retval EFI_SUCCESS The entry point is executed successfully.\r
715 @retval other Some error occurs when executing this entry point.\r
716\r
717**/\r
718EFI_STATUS\r
719EFIAPI\r
720InitializeDiskIo (\r
721 IN EFI_HANDLE ImageHandle,\r
722 IN EFI_SYSTEM_TABLE *SystemTable\r
723 )\r
724{\r
725 EFI_STATUS Status;\r
726\r
727 //\r
728 // Install driver model protocol(s).\r
729 //\r
d38a0f44 730 Status = EfiLibInstallDriverBindingComponentName2 (\r
adbcbf8f 731 ImageHandle,\r
732 SystemTable,\r
733 &gDiskIoDriverBinding,\r
734 ImageHandle,\r
735 &gDiskIoComponentName,\r
d38a0f44 736 &gDiskIoComponentName2\r
adbcbf8f 737 );\r
738 ASSERT_EFI_ERROR (Status);\r
739\r
740\r
741 return Status;\r
742}\r
743\r