]> git.proxmox.com Git - mirror_edk2.git/blob - UnixPkg/UnixBlockIoDxe/UnixBlockIo.c
Update the copyright notice format
[mirror_edk2.git] / UnixPkg / UnixBlockIoDxe / UnixBlockIo.c
1 /*++
2
3 Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 UnixBlockIo.c
15
16 Abstract:
17
18 Produce block IO abstractions for real devices on your PC using Posix APIs.
19 The configuration of what devices to mount or emulate comes from UNIX
20 environment variables. The variables must be visible to the Microsoft*
21 Developer Studio for them to work.
22
23 <F>ixed - Fixed disk like a hard drive.
24 <R>emovable - Removable media like a floppy or CD-ROM.
25 Read <O>nly - Write protected device.
26 Read <W>rite - Read write device.
27 <block count> - Decimal number of blocks a device supports.
28 <block size> - Decimal number of bytes per block.
29
30 UNIX envirnonment variable contents. '<' and '>' are not part of the variable,
31 they are just used to make this help more readable. There should be no
32 spaces between the ';'. Extra spaces will break the variable. A '!' is
33 used to seperate multiple devices in a variable.
34
35 EFI_UNIX_VIRTUAL_DISKS =
36 <F | R><O | W>;<block count>;<block size>[!...]
37
38 EFI_UNIX_PHYSICAL_DISKS =
39 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]
40
41 Virtual Disks: These devices use a file to emulate a hard disk or removable
42 media device.
43
44 Thus a 20 MB emulated hard drive would look like:
45 EFI_UNIX_VIRTUAL_DISKS=FW;40960;512
46
47 A 1.44MB emulated floppy with a block size of 1024 would look like:
48 EFI_UNIX_VIRTUAL_DISKS=RW;1440;1024
49
50 Physical Disks: These devices use UNIX to open a real device in your system
51
52 Thus a 120 MB floppy would look like:
53 EFI_UNIX_PHYSICAL_DISKS=B:RW;245760;512
54
55 Thus a standard CD-ROM floppy would look like:
56 EFI_UNIX_PHYSICAL_DISKS=Z:RO;307200;2048
57
58
59 * Other names and brands may be claimed as the property of others.
60
61 --*/
62
63 #include <fcntl.h>
64 #include <unistd.h>
65 #include "UnixBlockIo.h"
66
67 //
68 // Block IO protocol member functions
69 //
70 EFI_STATUS
71 EFIAPI
72 UnixBlockIoReadBlocks (
73 IN EFI_BLOCK_IO_PROTOCOL *This,
74 IN UINT32 MediaId,
75 IN EFI_LBA Lba,
76 IN UINTN BufferSize,
77 OUT VOID *Buffer
78 )
79 /*++
80
81 Routine Description:
82
83 TODO: Add function description
84
85 Arguments:
86
87 This - TODO: add argument description
88 MediaId - TODO: add argument description
89 Lba - TODO: add argument description
90 BufferSize - TODO: add argument description
91 Buffer - TODO: add argument description
92
93 Returns:
94
95 TODO: add return values
96
97 --*/
98 ;
99
100 EFI_STATUS
101 EFIAPI
102 UnixBlockIoWriteBlocks (
103 IN EFI_BLOCK_IO_PROTOCOL *This,
104 IN UINT32 MediaId,
105 IN EFI_LBA Lba,
106 IN UINTN BufferSize,
107 IN VOID *Buffer
108 )
109 /*++
110
111 Routine Description:
112
113 TODO: Add function description
114
115 Arguments:
116
117 This - TODO: add argument description
118 MediaId - TODO: add argument description
119 Lba - TODO: add argument description
120 BufferSize - TODO: add argument description
121 Buffer - TODO: add argument description
122
123 Returns:
124
125 TODO: add return values
126
127 --*/
128 ;
129
130 EFI_STATUS
131 EFIAPI
132 UnixBlockIoFlushBlocks (
133 IN EFI_BLOCK_IO_PROTOCOL *This
134 )
135 /*++
136
137 Routine Description:
138
139 TODO: Add function description
140
141 Arguments:
142
143 This - TODO: add argument description
144
145 Returns:
146
147 TODO: add return values
148
149 --*/
150 ;
151
152 EFI_STATUS
153 EFIAPI
154 UnixBlockIoResetBlock (
155 IN EFI_BLOCK_IO_PROTOCOL *This,
156 IN BOOLEAN ExtendedVerification
157 )
158 /*++
159
160 Routine Description:
161
162 TODO: Add function description
163
164 Arguments:
165
166 This - TODO: add argument description
167 ExtendedVerification - TODO: add argument description
168
169 Returns:
170
171 TODO: add return values
172
173 --*/
174 ;
175
176 //
177 // Private Worker functions
178 //
179 EFI_STATUS
180 UnixBlockIoCreateMapping (
181 IN EFI_UNIX_IO_PROTOCOL *UnixIo,
182 IN EFI_HANDLE EfiDeviceHandle,
183 IN CHAR16 *Filename,
184 IN BOOLEAN ReadOnly,
185 IN BOOLEAN RemovableMedia,
186 IN UINTN NumberOfBlocks,
187 IN UINTN BlockSize
188 )
189 /*++
190
191 Routine Description:
192
193 TODO: Add function description
194
195 Arguments:
196
197 UnixIo - TODO: add argument description
198 EfiDeviceHandle - TODO: add argument description
199 Filename - TODO: add argument description
200 ReadOnly - TODO: add argument description
201 RemovableMedia - TODO: add argument description
202 NumberOfBlocks - TODO: add argument description
203 BlockSize - TODO: add argument description
204 DeviceType - TODO: add argument description
205
206 Returns:
207
208 TODO: add return values
209
210 --*/
211 ;
212
213 EFI_STATUS
214 UnixBlockIoReadWriteCommon (
215 IN UNIX_BLOCK_IO_PRIVATE *Private,
216 IN UINT32 MediaId,
217 IN EFI_LBA Lba,
218 IN UINTN BufferSize,
219 IN VOID *Buffer,
220 IN CHAR8 *CallerName
221 )
222 /*++
223
224 Routine Description:
225
226 TODO: Add function description
227
228 Arguments:
229
230 Private - TODO: add argument description
231 MediaId - TODO: add argument description
232 Lba - TODO: add argument description
233 BufferSize - TODO: add argument description
234 Buffer - TODO: add argument description
235 CallerName - TODO: add argument description
236
237 Returns:
238
239 TODO: add return values
240
241 --*/
242 ;
243
244 EFI_STATUS
245 UnixBlockIoError (
246 IN UNIX_BLOCK_IO_PRIVATE *Private
247 )
248 /*++
249
250 Routine Description:
251
252 TODO: Add function description
253
254 Arguments:
255
256 Private - TODO: add argument description
257
258 Returns:
259
260 TODO: add return values
261
262 --*/
263 ;
264
265 EFI_STATUS
266 UnixBlockIoOpenDevice (
267 UNIX_BLOCK_IO_PRIVATE *Private
268 )
269 /*++
270
271 Routine Description:
272
273 TODO: Add function description
274
275 Arguments:
276
277 Private - TODO: add argument description
278
279 Returns:
280
281 TODO: add return values
282
283 --*/
284 ;
285
286 CHAR16 *
287 GetNextElementPastTerminator (
288 IN CHAR16 *EnvironmentVariable,
289 IN CHAR16 Terminator
290 )
291 /*++
292
293 Routine Description:
294
295 TODO: Add function description
296
297 Arguments:
298
299 EnvironmentVariable - TODO: add argument description
300 Terminator - TODO: add argument description
301
302 Returns:
303
304 TODO: add return values
305
306 --*/
307 ;
308 EFI_DRIVER_BINDING_PROTOCOL gUnixBlockIoDriverBinding = {
309 UnixBlockIoDriverBindingSupported,
310 UnixBlockIoDriverBindingStart,
311 UnixBlockIoDriverBindingStop,
312 0xa,
313 NULL,
314 NULL
315 };
316
317 EFI_STATUS
318 EFIAPI
319 UnixBlockIoDriverBindingSupported (
320 IN EFI_DRIVER_BINDING_PROTOCOL *This,
321 IN EFI_HANDLE Handle,
322 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
323 )
324 /*++
325
326 Routine Description:
327
328 Arguments:
329
330 Returns:
331
332 None
333
334 --*/
335 // TODO: This - add argument and description to function comment
336 // TODO: Handle - add argument and description to function comment
337 // TODO: RemainingDevicePath - add argument and description to function comment
338 {
339 EFI_STATUS Status;
340 EFI_UNIX_IO_PROTOCOL *UnixIo;
341
342 //
343 // Open the IO Abstraction(s) needed to perform the supported test
344 //
345 Status = gBS->OpenProtocol (
346 Handle,
347 &gEfiUnixIoProtocolGuid,
348 (VOID **)&UnixIo,
349 This->DriverBindingHandle,
350 Handle,
351 EFI_OPEN_PROTOCOL_BY_DRIVER
352 );
353 if (EFI_ERROR (Status)) {
354 return Status;
355 }
356
357 //
358 // Make sure the UnixThunkProtocol is valid
359 //
360 Status = EFI_UNSUPPORTED;
361 if (UnixIo->UnixThunk->Signature == EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) {
362
363 //
364 // Check the GUID to see if this is a handle type the driver supports
365 //
366 if (CompareGuid (UnixIo->TypeGuid, &gEfiUnixVirtualDisksGuid) ) {
367 Status = EFI_SUCCESS;
368 }
369 }
370
371 //
372 // Close the I/O Abstraction(s) used to perform the supported test
373 //
374 gBS->CloseProtocol (
375 Handle,
376 &gEfiUnixIoProtocolGuid,
377 This->DriverBindingHandle,
378 Handle
379 );
380 return Status;
381 }
382
383 EFI_STATUS
384 EFIAPI
385 UnixBlockIoDriverBindingStart (
386 IN EFI_DRIVER_BINDING_PROTOCOL *This,
387 IN EFI_HANDLE Handle,
388 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
389 )
390 /*++
391
392 Routine Description:
393
394 Arguments:
395
396 Returns:
397
398 None
399
400 --*/
401 // TODO: This - add argument and description to function comment
402 // TODO: Handle - add argument and description to function comment
403 // TODO: RemainingDevicePath - add argument and description to function comment
404 {
405 EFI_STATUS Status;
406 EFI_UNIX_IO_PROTOCOL *UnixIo;
407 CHAR16 Buffer[FILENAME_BUFFER_SIZE];
408 CHAR16 *Str;
409 BOOLEAN RemovableMedia;
410 BOOLEAN WriteProtected;
411 UINTN NumberOfBlocks;
412 UINTN BlockSize;
413 INTN i;
414
415 //
416 // Grab the protocols we need
417 //
418
419 Status = gBS->OpenProtocol (
420 Handle,
421 &gEfiUnixIoProtocolGuid,
422 (void *)&UnixIo,
423 This->DriverBindingHandle,
424 Handle,
425 EFI_OPEN_PROTOCOL_BY_DRIVER
426 );
427 if (EFI_ERROR (Status)) {
428 return Status;
429 }
430 //
431 // Set DiskType
432 //
433 if (!CompareGuid (UnixIo->TypeGuid, &gEfiUnixVirtualDisksGuid)) {
434 Status = EFI_UNSUPPORTED;
435 goto Done;
436 }
437
438 Status = EFI_NOT_FOUND;
439 // Extract filename.
440 Str = UnixIo->EnvString;
441 i = 0;
442 while (*Str && *Str != ':')
443 Buffer[i++] = *Str++;
444 Buffer[i] = 0;
445 if (*Str != ':') {
446 goto Done;
447 }
448
449 Str++;
450
451 RemovableMedia = FALSE;
452 WriteProtected = TRUE;
453 NumberOfBlocks = 0;
454 BlockSize = 512;
455 do {
456 if (*Str == 'R' || *Str == 'F') {
457 RemovableMedia = (BOOLEAN) (*Str == 'R');
458 Str++;
459 }
460 if (*Str == 'O' || *Str == 'W') {
461 WriteProtected = (BOOLEAN) (*Str == 'O');
462 Str++;
463 }
464 if (*Str == 0)
465 break;
466 if (*Str != ';')
467 goto Done;
468 Str++;
469
470 NumberOfBlocks = Atoi (Str);
471 Str = GetNextElementPastTerminator (Str, ';');
472 if (NumberOfBlocks == 0)
473 break;
474
475 BlockSize = Atoi (Str);
476 if (BlockSize != 0)
477 Str = GetNextElementPastTerminator (Str, ';');
478 } while (0);
479
480 //
481 // If we get here the variable is valid so do the work.
482 //
483 Status = UnixBlockIoCreateMapping (
484 UnixIo,
485 Handle,
486 Buffer,
487 WriteProtected,
488 RemovableMedia,
489 NumberOfBlocks,
490 BlockSize
491 );
492
493 Done:
494 if (EFI_ERROR (Status)) {
495 gBS->CloseProtocol (
496 Handle,
497 &gEfiUnixIoProtocolGuid,
498 This->DriverBindingHandle,
499 Handle
500 );
501 }
502
503 return Status;
504 }
505
506 EFI_STATUS
507 EFIAPI
508 UnixBlockIoDriverBindingStop (
509 IN EFI_DRIVER_BINDING_PROTOCOL *This,
510 IN EFI_HANDLE Handle,
511 IN UINTN NumberOfChildren,
512 IN EFI_HANDLE *ChildHandleBuffer
513 )
514 /*++
515
516 Routine Description:
517
518 TODO: Add function description
519
520 Arguments:
521
522 This - TODO: add argument description
523 Handle - TODO: add argument description
524 NumberOfChildren - TODO: add argument description
525 ChildHandleBuffer - TODO: add argument description
526
527 Returns:
528
529 EFI_UNSUPPORTED - TODO: Add description for return value
530
531 --*/
532 {
533 EFI_BLOCK_IO_PROTOCOL *BlockIo;
534 EFI_STATUS Status;
535 UNIX_BLOCK_IO_PRIVATE *Private;
536
537 //
538 // Get our context back
539 //
540 Status = gBS->OpenProtocol (
541 Handle,
542 &gEfiBlockIoProtocolGuid,
543 (void *)&BlockIo,
544 This->DriverBindingHandle,
545 Handle,
546 EFI_OPEN_PROTOCOL_GET_PROTOCOL
547 );
548 if (EFI_ERROR (Status)) {
549 return EFI_UNSUPPORTED;
550 }
551
552 Private = UNIX_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo);
553
554 //
555 // BugBug: If we need to kick people off, we need to make Uninstall Close the handles.
556 // We could pass in our image handle or FLAG our open to be closed via
557 // Unistall (== to saying any CloseProtocol will close our open)
558 //
559 Status = gBS->UninstallMultipleProtocolInterfaces (
560 Private->EfiHandle,
561 &gEfiBlockIoProtocolGuid,
562 &Private->BlockIo,
563 NULL
564 );
565 if (!EFI_ERROR (Status)) {
566
567 Status = gBS->CloseProtocol (
568 Handle,
569 &gEfiUnixIoProtocolGuid,
570 This->DriverBindingHandle,
571 Handle
572 );
573
574 //
575 // Shut down our device
576 //
577 Private->UnixThunk->Close (Private->fd);
578
579 //
580 // Free our instance data
581 //
582 FreeUnicodeStringTable (Private->ControllerNameTable);
583
584 gBS->FreePool (Private);
585 }
586
587 return Status;
588 }
589
590 CHAR16 *
591 GetNextElementPastTerminator (
592 IN CHAR16 *EnvironmentVariable,
593 IN CHAR16 Terminator
594 )
595 /*++
596
597 Routine Description:
598
599 Worker function to parse environment variables.
600
601 Arguments:
602 EnvironmentVariable - Envirnment variable to parse.
603
604 Terminator - Terminator to parse for.
605
606 Returns:
607
608 Pointer to next eliment past the first occurence of Terminator or the '\0'
609 at the end of the string.
610
611 --*/
612 {
613 CHAR16 *Ptr;
614
615 for (Ptr = EnvironmentVariable; *Ptr != '\0'; Ptr++) {
616 if (*Ptr == Terminator) {
617 Ptr++;
618 break;
619 }
620 }
621
622 return Ptr;
623 }
624
625 EFI_STATUS
626 UnixBlockIoCreateMapping (
627 IN EFI_UNIX_IO_PROTOCOL *UnixIo,
628 IN EFI_HANDLE EfiDeviceHandle,
629 IN CHAR16 *Filename,
630 IN BOOLEAN ReadOnly,
631 IN BOOLEAN RemovableMedia,
632 IN UINTN NumberOfBlocks,
633 IN UINTN BlockSize
634 )
635 /*++
636
637 Routine Description:
638
639 TODO: Add function description
640
641 Arguments:
642
643 UnixIo - TODO: add argument description
644 EfiDeviceHandle - TODO: add argument description
645 Filename - TODO: add argument description
646 ReadOnly - TODO: add argument description
647 RemovableMedia - TODO: add argument description
648 NumberOfBlocks - TODO: add argument description
649 BlockSize - TODO: add argument description
650 DeviceType - TODO: add argument description
651
652 Returns:
653
654 TODO: add return values
655
656 --*/
657 {
658 EFI_STATUS Status;
659 EFI_BLOCK_IO_PROTOCOL *BlockIo;
660 UNIX_BLOCK_IO_PRIVATE *Private;
661 UINTN Index;
662
663 Status = gBS->AllocatePool (
664 EfiBootServicesData,
665 sizeof (UNIX_BLOCK_IO_PRIVATE),
666 (void *)&Private
667 );
668 ASSERT_EFI_ERROR (Status);
669
670 EfiInitializeLock (&Private->Lock, TPL_NOTIFY);
671
672 Private->UnixThunk = UnixIo->UnixThunk;
673
674 Private->Signature = UNIX_BLOCK_IO_PRIVATE_SIGNATURE;
675 Private->LastBlock = NumberOfBlocks - 1;
676 Private->BlockSize = BlockSize;
677
678 for (Index = 0; Filename[Index] != 0; Index++) {
679 Private->Filename[Index] = Filename[Index];
680 }
681
682 Private->Filename[Index] = 0;
683
684 Private->Mode = (ReadOnly ? O_RDONLY : O_RDWR);
685
686 Private->NumberOfBlocks = NumberOfBlocks;
687 Private->fd = -1;
688
689 Private->ControllerNameTable = NULL;
690
691 AddUnicodeString (
692 "eng",
693 gUnixBlockIoComponentName.SupportedLanguages,
694 &Private->ControllerNameTable,
695 Filename
696 );
697
698 BlockIo = &Private->BlockIo;
699 BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
700 BlockIo->Media = &Private->Media;
701 BlockIo->Media->BlockSize = Private->BlockSize;
702 BlockIo->Media->LastBlock = Private->NumberOfBlocks - 1;
703 BlockIo->Media->MediaId = 0;;
704
705 BlockIo->Reset = UnixBlockIoResetBlock;
706 BlockIo->ReadBlocks = UnixBlockIoReadBlocks;
707 BlockIo->WriteBlocks = UnixBlockIoWriteBlocks;
708 BlockIo->FlushBlocks = UnixBlockIoFlushBlocks;
709
710 BlockIo->Media->ReadOnly = ReadOnly;
711 BlockIo->Media->RemovableMedia = RemovableMedia;
712 BlockIo->Media->LogicalPartition = FALSE;
713 BlockIo->Media->MediaPresent = TRUE;
714 BlockIo->Media->WriteCaching = FALSE;
715
716 BlockIo->Media->IoAlign = 1;
717
718 Private->EfiHandle = EfiDeviceHandle;
719 Status = UnixBlockIoOpenDevice (Private);
720 if (!EFI_ERROR (Status)) {
721
722 Status = gBS->InstallMultipleProtocolInterfaces (
723 &Private->EfiHandle,
724 &gEfiBlockIoProtocolGuid,
725 &Private->BlockIo,
726 NULL
727 );
728 if (EFI_ERROR (Status)) {
729 FreeUnicodeStringTable (Private->ControllerNameTable);
730 gBS->FreePool (Private);
731 }
732
733 DEBUG ((EFI_D_ERROR, "BlockDevice added: %s\n", Filename));
734 }
735
736 return Status;
737 }
738
739 EFI_STATUS
740 UnixBlockIoOpenDevice (
741 UNIX_BLOCK_IO_PRIVATE *Private
742 )
743 /*++
744
745 Routine Description:
746
747 TODO: Add function description
748
749 Arguments:
750
751 Private - TODO: add argument description
752
753 Returns:
754
755 TODO: add return values
756
757 --*/
758 {
759 EFI_STATUS Status;
760 UINT64 FileSize;
761 UINT64 EndOfFile;
762 EFI_BLOCK_IO_PROTOCOL *BlockIo;
763
764 BlockIo = &Private->BlockIo;
765 EfiAcquireLock (&Private->Lock);
766
767 //
768 // If the device is already opened, close it
769 //
770 if (Private->fd >= 0) {
771 BlockIo->Reset (BlockIo, FALSE);
772 }
773
774 //
775 // Open the device
776 //
777 Private->fd = Private->UnixThunk->Open (Private->Filename, Private->Mode, 0644);
778 if (Private->fd < 0) {
779 DEBUG ((EFI_D_INFO, "PlOpenBlock: Could not open %a\n", Private->Filename));
780 BlockIo->Media->MediaPresent = FALSE;
781 Status = EFI_NO_MEDIA;
782 goto Done;
783 }
784
785 if (!BlockIo->Media->MediaPresent) {
786 //
787 // BugBug: try to emulate if a CD appears - notify drivers to check it out
788 //
789 BlockIo->Media->MediaPresent = TRUE;
790 EfiReleaseLock (&Private->Lock);
791 EfiAcquireLock (&Private->Lock);
792 }
793
794 //
795 // get the size of the file
796 //
797 Status = SetFilePointer64 (Private, 0, &FileSize, SEEK_END);
798 if (EFI_ERROR (Status)) {
799 FileSize = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
800 DEBUG ((EFI_D_ERROR, "PlOpenBlock: Could not get filesize of %a\n", Private->Filename));
801 Status = EFI_UNSUPPORTED;
802 goto Done;
803 }
804
805 if (Private->NumberOfBlocks == 0) {
806 Private->NumberOfBlocks = DivU64x32 (FileSize, Private->BlockSize);
807 Private->LastBlock = Private->NumberOfBlocks - 1;
808 Private->Media.LastBlock = Private->LastBlock;
809 }
810
811 EndOfFile = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
812
813 if (FileSize != EndOfFile) {
814 //
815 // file is not the proper size, change it
816 //
817 DEBUG ((EFI_D_INIT, "PlOpenBlock: Initializing block device: %a\n", Private->Filename));
818
819 //
820 // first set it to 0
821 //
822 Private->UnixThunk->FTruncate (Private->fd, 0);
823
824 //
825 // then set it to the needed file size (OS will zero fill it)
826 //
827 Private->UnixThunk->FTruncate (Private->fd, EndOfFile);
828 }
829
830 DEBUG ((EFI_D_INIT, "%HPlOpenBlock: opened %a%N\n", Private->Filename));
831 Status = EFI_SUCCESS;
832
833 Done:
834 if (EFI_ERROR (Status)) {
835 if (Private->fd >= 0) {
836 BlockIo->Reset (BlockIo, FALSE);
837 }
838 }
839
840 EfiReleaseLock (&Private->Lock);
841 return Status;
842 }
843
844 EFI_STATUS
845 UnixBlockIoError (
846 IN UNIX_BLOCK_IO_PRIVATE *Private
847 )
848 /*++
849
850 Routine Description:
851
852 TODO: Add function description
853
854 Arguments:
855
856 Private - TODO: add argument description
857
858 Returns:
859
860 TODO: add return values
861
862 --*/
863 {
864 return EFI_DEVICE_ERROR;
865
866 #if 0
867 EFI_BLOCK_IO_PROTOCOL *BlockIo;
868 EFI_STATUS Status;
869 BOOLEAN ReinstallBlockIoFlag;
870
871
872 BlockIo = &Private->BlockIo;
873
874 switch (Private->UnixThunk->GetLastError ()) {
875
876 case ERROR_NOT_READY:
877 Status = EFI_NO_MEDIA;
878 BlockIo->Media->ReadOnly = FALSE;
879 BlockIo->Media->MediaPresent = FALSE;
880 ReinstallBlockIoFlag = FALSE;
881 break;
882
883 case ERROR_WRONG_DISK:
884 BlockIo->Media->ReadOnly = FALSE;
885 BlockIo->Media->MediaPresent = TRUE;
886 BlockIo->Media->MediaId += 1;
887 ReinstallBlockIoFlag = TRUE;
888 Status = EFI_MEDIA_CHANGED;
889 break;
890
891 case ERROR_WRITE_PROTECT:
892 BlockIo->Media->ReadOnly = TRUE;
893 ReinstallBlockIoFlag = FALSE;
894 Status = EFI_WRITE_PROTECTED;
895 break;
896
897 default:
898 ReinstallBlockIoFlag = FALSE;
899 Status = EFI_DEVICE_ERROR;
900 break;
901 }
902
903 if (ReinstallBlockIoFlag) {
904 BlockIo->Reset (BlockIo, FALSE);
905
906 gBS->ReinstallProtocolInterface (
907 Private->EfiHandle,
908 &gEfiBlockIoProtocolGuid,
909 BlockIo,
910 BlockIo
911 );
912 }
913
914 return Status;
915 #endif
916 }
917
918 EFI_STATUS
919 UnixBlockIoReadWriteCommon (
920 IN UNIX_BLOCK_IO_PRIVATE *Private,
921 IN UINT32 MediaId,
922 IN EFI_LBA Lba,
923 IN UINTN BufferSize,
924 IN VOID *Buffer,
925 IN CHAR8 *CallerName
926 )
927 /*++
928
929 Routine Description:
930
931 TODO: Add function description
932
933 Arguments:
934
935 Private - TODO: add argument description
936 MediaId - TODO: add argument description
937 Lba - TODO: add argument description
938 BufferSize - TODO: add argument description
939 Buffer - TODO: add argument description
940 CallerName - TODO: add argument description
941
942 Returns:
943
944 EFI_NO_MEDIA - TODO: Add description for return value
945 EFI_MEDIA_CHANGED - TODO: Add description for return value
946 EFI_INVALID_PARAMETER - TODO: Add description for return value
947 EFI_SUCCESS - TODO: Add description for return value
948 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
949 EFI_INVALID_PARAMETER - TODO: Add description for return value
950 EFI_SUCCESS - TODO: Add description for return value
951
952 --*/
953 {
954 EFI_STATUS Status;
955 UINTN BlockSize;
956 UINT64 LastBlock;
957 INT64 DistanceToMove;
958 UINT64 DistanceMoved;
959
960 if (Private->fd < 0) {
961 Status = UnixBlockIoOpenDevice (Private);
962 if (EFI_ERROR (Status)) {
963 return Status;
964 }
965 }
966
967 if (!Private->Media.MediaPresent) {
968 DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName));
969 return EFI_NO_MEDIA;
970 }
971
972 if (Private->Media.MediaId != MediaId) {
973 return EFI_MEDIA_CHANGED;
974 }
975
976 if ((UINT32) Buffer % Private->Media.IoAlign != 0) {
977 return EFI_INVALID_PARAMETER;
978 }
979
980 //
981 // Verify buffer size
982 //
983 BlockSize = Private->BlockSize;
984 if (BufferSize == 0) {
985 DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName));
986 return EFI_SUCCESS;
987 }
988
989 if ((BufferSize % BlockSize) != 0) {
990 DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName));
991 return EFI_BAD_BUFFER_SIZE;
992 }
993
994 LastBlock = Lba + (BufferSize / BlockSize) - 1;
995 if (LastBlock > Private->LastBlock) {
996 DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n"));
997 return EFI_INVALID_PARAMETER;
998 }
999 //
1000 // Seek to End of File
1001 //
1002 DistanceToMove = MultU64x32 (Lba, BlockSize);
1003 Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, SEEK_SET);
1004
1005 if (EFI_ERROR (Status)) {
1006 DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n"));
1007 return UnixBlockIoError (Private);
1008 }
1009
1010 return EFI_SUCCESS;
1011 }
1012
1013 EFI_STATUS
1014 EFIAPI
1015 UnixBlockIoReadBlocks (
1016 IN EFI_BLOCK_IO_PROTOCOL *This,
1017 IN UINT32 MediaId,
1018 IN EFI_LBA Lba,
1019 IN UINTN BufferSize,
1020 OUT VOID *Buffer
1021 )
1022 /*++
1023
1024 Routine Description:
1025 Read BufferSize bytes from Lba into Buffer.
1026
1027 Arguments:
1028 This - Protocol instance pointer.
1029 MediaId - Id of the media, changes every time the media is replaced.
1030 Lba - The starting Logical Block Address to read from
1031 BufferSize - Size of Buffer, must be a multiple of device block size.
1032 Buffer - Buffer containing read data
1033
1034 Returns:
1035 EFI_SUCCESS - The data was read correctly from the device.
1036 EFI_DEVICE_ERROR - The device reported an error while performing the read.
1037 EFI_NO_MEDIA - There is no media in the device.
1038 EFI_MEDIA_CHANGED - The MediaId does not matched the current device.
1039 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
1040 device.
1041 EFI_INVALID_PARAMETER - The read request contains device addresses that are not
1042 valid for the device.
1043
1044 --*/
1045 {
1046 UNIX_BLOCK_IO_PRIVATE *Private;
1047 ssize_t len;
1048 EFI_STATUS Status;
1049 EFI_TPL OldTpl;
1050
1051 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1052
1053 Private = UNIX_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
1054
1055 Status = UnixBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "UnixReadBlocks");
1056 if (EFI_ERROR (Status)) {
1057 goto Done;
1058 }
1059
1060 len = Private->UnixThunk->Read (Private->fd, Buffer, BufferSize);
1061 if (len != BufferSize) {
1062 DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed.\n"));
1063 Status = UnixBlockIoError (Private);
1064 goto Done;
1065 }
1066
1067 //
1068 // If we wrote then media is present.
1069 //
1070 This->Media->MediaPresent = TRUE;
1071 Status = EFI_SUCCESS;
1072
1073 Done:
1074 gBS->RestoreTPL (OldTpl);
1075 return Status;
1076 }
1077
1078 EFI_STATUS
1079 EFIAPI
1080 UnixBlockIoWriteBlocks (
1081 IN EFI_BLOCK_IO_PROTOCOL *This,
1082 IN UINT32 MediaId,
1083 IN EFI_LBA Lba,
1084 IN UINTN BufferSize,
1085 IN VOID *Buffer
1086 )
1087 /*++
1088
1089 Routine Description:
1090 Write BufferSize bytes from Lba into Buffer.
1091
1092 Arguments:
1093 This - Protocol instance pointer.
1094 MediaId - Id of the media, changes every time the media is replaced.
1095 Lba - The starting Logical Block Address to read from
1096 BufferSize - Size of Buffer, must be a multiple of device block size.
1097 Buffer - Buffer containing read data
1098
1099 Returns:
1100 EFI_SUCCESS - The data was written correctly to the device.
1101 EFI_WRITE_PROTECTED - The device can not be written to.
1102 EFI_DEVICE_ERROR - The device reported an error while performing the write.
1103 EFI_NO_MEDIA - There is no media in the device.
1104 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
1105 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
1106 device.
1107 EFI_INVALID_PARAMETER - The write request contains a LBA that is not
1108 valid for the device.
1109
1110 --*/
1111 {
1112 UNIX_BLOCK_IO_PRIVATE *Private;
1113 ssize_t len;
1114 EFI_STATUS Status;
1115 EFI_TPL OldTpl;
1116
1117 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1118
1119 Private = UNIX_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
1120
1121 Status = UnixBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "UnixWriteBlocks");
1122 if (EFI_ERROR (Status)) {
1123 goto Done;
1124 }
1125
1126 len = Private->UnixThunk->Write (Private->fd, Buffer, BufferSize);
1127 if (len != BufferSize) {
1128 DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed.\n"));
1129 Status = UnixBlockIoError (Private);
1130 goto Done;
1131 }
1132
1133 //
1134 // If the write succeeded, we are not write protected and media is present.
1135 //
1136 This->Media->MediaPresent = TRUE;
1137 This->Media->ReadOnly = FALSE;
1138 Status = EFI_SUCCESS;
1139
1140 Done:
1141 gBS->RestoreTPL (OldTpl);
1142 return Status;
1143 }
1144
1145 EFI_STATUS
1146 EFIAPI
1147 UnixBlockIoFlushBlocks (
1148 IN EFI_BLOCK_IO_PROTOCOL *This
1149 )
1150 /*++
1151
1152 Routine Description:
1153 Flush the Block Device.
1154
1155 Arguments:
1156 This - Protocol instance pointer.
1157
1158 Returns:
1159 EFI_SUCCESS - All outstanding data was written to the device
1160 EFI_DEVICE_ERROR - The device reported an error while writting back the data
1161 EFI_NO_MEDIA - There is no media in the device.
1162
1163 --*/
1164 {
1165 return EFI_SUCCESS;
1166 }
1167
1168 EFI_STATUS
1169 EFIAPI
1170 UnixBlockIoResetBlock (
1171 IN EFI_BLOCK_IO_PROTOCOL *This,
1172 IN BOOLEAN ExtendedVerification
1173 )
1174 /*++
1175
1176 Routine Description:
1177 Reset the Block Device.
1178
1179 Arguments:
1180 This - Protocol instance pointer.
1181 ExtendedVerification - Driver may perform diagnostics on reset.
1182
1183 Returns:
1184 EFI_SUCCESS - The device was reset.
1185 EFI_DEVICE_ERROR - The device is not functioning properly and could
1186 not be reset.
1187
1188 --*/
1189 {
1190 UNIX_BLOCK_IO_PRIVATE *Private;
1191 EFI_TPL OldTpl;
1192
1193 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1194
1195 Private = UNIX_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
1196
1197 if (Private->fd >= 0) {
1198 Private->UnixThunk->Close (Private->fd);
1199 Private->fd = -1;
1200 }
1201
1202 gBS->RestoreTPL (OldTpl);
1203
1204 return EFI_SUCCESS;
1205 }
1206
1207 UINTN
1208 Atoi (
1209 CHAR16 *String
1210 )
1211 /*++
1212
1213 Routine Description:
1214
1215 Convert a unicode string to a UINTN
1216
1217 Arguments:
1218
1219 String - Unicode string.
1220
1221 Returns:
1222
1223 UINTN of the number represented by String.
1224
1225 --*/
1226 {
1227 UINTN Number;
1228 CHAR16 *Str;
1229
1230 //
1231 // skip preceeding white space
1232 //
1233 Str = String;
1234 while ((*Str) && (*Str == ' ')) {
1235 Str++;
1236 }
1237 //
1238 // Convert ot a Number
1239 //
1240 Number = 0;
1241 while (*Str != '\0') {
1242 if ((*Str >= '0') && (*Str <= '9')) {
1243 Number = (Number * 10) +*Str - '0';
1244 } else {
1245 break;
1246 }
1247
1248 Str++;
1249 }
1250
1251 return Number;
1252 }
1253
1254 EFI_STATUS
1255 SetFilePointer64 (
1256 IN UNIX_BLOCK_IO_PRIVATE *Private,
1257 IN INT64 DistanceToMove,
1258 OUT UINT64 *NewFilePointer,
1259 IN INTN MoveMethod
1260 )
1261 /*++
1262
1263 This function extends the capability of SetFilePointer to accept 64 bit parameters
1264
1265 --*/
1266 // TODO: function comment is missing 'Routine Description:'
1267 // TODO: function comment is missing 'Arguments:'
1268 // TODO: function comment is missing 'Returns:'
1269 // TODO: Private - add argument and description to function comment
1270 // TODO: DistanceToMove - add argument and description to function comment
1271 // TODO: NewFilePointer - add argument and description to function comment
1272 // TODO: MoveMethod - add argument and description to function comment
1273 {
1274 EFI_STATUS Status;
1275 off_t res;
1276
1277 Status = EFI_SUCCESS;
1278 res = Private->UnixThunk->Lseek(Private->fd, DistanceToMove, MoveMethod);
1279 if (res == -1) {
1280 Status = EFI_INVALID_PARAMETER;
1281 }
1282
1283 if (NewFilePointer != NULL) {
1284 *NewFilePointer = res;
1285 }
1286
1287 return Status;
1288 }