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