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