]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/Uefi/Devices/UefiShell/daShell.c
StdLib: Improve robustness of stat() and make basename() a public function.
[mirror_edk2.git] / StdLib / LibC / Uefi / Devices / UefiShell / daShell.c
CommitLineData
53e1e5c6 1/** @file\r
2 Abstract device driver for the UEFI Shell-hosted environment.\r
3\r
4 In a Shell-hosted environment, this is the driver that is called\r
5 when no other driver matches.\r
6\r
7 Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
8 This program and the accompanying materials are licensed and made available under\r
9 the terms and conditions of the BSD License that accompanies this distribution.\r
10 The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16**/\r
17#include <Uefi.h>\r
18#include <Library/BaseLib.h>\r
19#include <Library/MemoryAllocationLib.h>\r
20#include <Library/UefiBootServicesTableLib.h>\r
21#include <Library/ShellLib.h>\r
22\r
23#include <LibConfig.h>\r
24#include <sys/EfiSysCall.h>\r
25\r
26#include <errno.h>\r
27#include <string.h>\r
28#include <stdlib.h>\r
76beedc0 29#include <stdarg.h>\r
53e1e5c6 30#include <wctype.h>\r
31#include <wchar.h>\r
32#include <sys/fcntl.h>\r
d7ce7006 33#include <sys/syslimits.h>\r
53e1e5c6 34#include <kfile.h>\r
35#include <Device/Device.h>\r
36#include <MainData.h>\r
37#include <Efi/SysEfi.h>\r
38\r
39static\r
40int\r
41EFIAPI\r
42da_ShellClose(\r
43 IN struct __filedes *Fp\r
44)\r
45{\r
46 EFIerrno = ShellCloseFile( (SHELL_FILE_HANDLE *)&Fp->devdata);\r
47 if(RETURN_ERROR(EFIerrno)) {\r
48 return -1;\r
49 }\r
50 return 0;\r
51}\r
52\r
53static\r
54int\r
55EFIAPI\r
56da_ShellDelete(\r
57 struct __filedes *filp\r
58 )\r
59{\r
60 RETURN_STATUS Status;\r
61\r
62 Status = ShellDeleteFile( (SHELL_FILE_HANDLE *)&filp->devdata);\r
63 if(Status != RETURN_SUCCESS) {\r
64 errno = EFI2errno(Status);\r
65 EFIerrno = Status;\r
66 return -1;\r
67 }\r
68 return 0;\r
69}\r
70\r
71static\r
72off_t\r
73EFIAPI\r
74da_ShellSeek(\r
75 struct __filedes *filp,\r
76 off_t offset,\r
77 int whence\r
78)\r
79{\r
80 __off_t CurPos = -1;\r
81 RETURN_STATUS Status = RETURN_SUCCESS;\r
82 SHELL_FILE_HANDLE FileHandle;\r
83\r
84 FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
85\r
86 if(whence != SEEK_SET) {\r
87 // We are doing a relative seek\r
88 if(whence == SEEK_END) {\r
89 // seeking relative to EOF, so position there first.\r
90 Status = ShellSetFilePosition( FileHandle, 0xFFFFFFFFFFFFFFFFULL);\r
91 }\r
92 if(Status == RETURN_SUCCESS) {\r
93 // Now, determine our current position.\r
94 Status = ShellGetFilePosition( FileHandle, (UINT64 *)&CurPos);\r
95 }\r
96 }\r
97 else {\r
98 CurPos = 0; // offset is an absolute position for SEEK_SET\r
99 if(offset < 0) {\r
100 Status = RETURN_INVALID_PARAMETER;\r
101 }\r
102 }\r
103 if(Status == RETURN_SUCCESS) {\r
104 /* CurPos now indicates the point we are seeking from, so seek... */\r
105 Status = ShellSetFilePosition( FileHandle, (UINT64)(CurPos + offset));\r
106 if(Status == RETURN_SUCCESS) {\r
107 // Now, determine our final position.\r
108 Status = ShellGetFilePosition( FileHandle, (UINT64 *)&CurPos);\r
109 }\r
110 }\r
111 if(Status != RETURN_SUCCESS) {\r
112 if(Status == EFI_UNSUPPORTED) {\r
113 errno = EISDIR;\r
114 }\r
115 else {\r
116 errno = EFI2errno(Status);\r
117 }\r
118 EFIerrno = Status;\r
119 CurPos = EOF;\r
120 }\r
121 return CurPos;\r
122}\r
123\r
124/** The directory path is created with the access permissions specified by\r
125 perms.\r
126\r
127 The directory is closed after it is created.\r
128\r
129 @retval 0 The directory was created successfully.\r
130 @retval -1 An error occurred and an error code is stored in errno.\r
131**/\r
132static\r
133int\r
134EFIAPI\r
135da_ShellMkdir(\r
136 const char *path,\r
137 __mode_t perms\r
138 )\r
139{\r
140 SHELL_FILE_HANDLE FileHandle;\r
141 RETURN_STATUS Status;\r
142 EFI_FILE_INFO *FileInfo;\r
143 wchar_t *NewPath;\r
144 int retval = -1;\r
145\r
146 // Convert name from MBCS to WCS and change '/' to '\\'\r
147 NewPath = NormalizePath( path);\r
148\r
149 if(NewPath != NULL) {\r
150 Status = ShellCreateDirectory( NewPath, &FileHandle);\r
151 if(Status == RETURN_SUCCESS) {\r
152 FileInfo = ShellGetFileInfo( FileHandle);\r
153 Status = RETURN_ABORTED; // In case ShellGetFileInfo() failed\r
154 if(FileInfo != NULL) {\r
155 FileInfo->Attribute = Omode2EFI(perms);\r
156 Status = ShellSetFileInfo( FileHandle, FileInfo);\r
157 FreePool(FileInfo);\r
158 if(Status == RETURN_SUCCESS) {\r
159 (void)ShellCloseFile(&FileHandle);\r
160 retval = 0;\r
161 }\r
162 }\r
163 }\r
164 errno = EFI2errno(Status);\r
165 EFIerrno = Status;\r
166 free(NewPath);\r
167 }\r
168 return retval;\r
169}\r
170\r
171static\r
172ssize_t\r
173EFIAPI\r
174da_ShellRead(\r
175 IN OUT struct __filedes *filp,\r
176 IN OUT off_t *offset,\r
177 IN size_t BufferSize,\r
178 OUT VOID *Buffer\r
179)\r
180{\r
181 ssize_t BufSize;\r
182 SHELL_FILE_HANDLE FileHandle;\r
183 RETURN_STATUS Status;\r
184\r
185 if(offset != NULL) {\r
186 BufSize = (ssize_t)da_ShellSeek(filp, *offset, SEEK_SET);\r
187 if(BufSize >= 0) {\r
188 filp->f_offset = BufSize;\r
189 }\r
190 }\r
191\r
192 BufSize = (ssize_t)BufferSize;\r
193 FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
194\r
195 Status = ShellReadFile( FileHandle, (UINTN *)&BufSize, Buffer);\r
196 if(Status != RETURN_SUCCESS) {\r
197 EFIerrno = Status;\r
198 errno = EFI2errno(Status);\r
199 if(Status == RETURN_BUFFER_TOO_SMALL) {\r
200 BufSize = -BufSize;\r
201 }\r
202 else {\r
203 BufSize = -1;\r
204 }\r
205 }\r
206 else {\r
207 filp->f_offset += BufSize; // Advance to where we want to read next.\r
208 }\r
209 return BufSize;\r
210}\r
211\r
212static\r
213ssize_t\r
214EFIAPI\r
215da_ShellWrite(\r
216 IN struct __filedes *filp,\r
217 IN off_t *offset,\r
218 IN size_t BufferSize,\r
219 IN const void *Buffer\r
220 )\r
221{\r
222 ssize_t BufSize;\r
223 SHELL_FILE_HANDLE FileHandle;\r
224 RETURN_STATUS Status;\r
225 off_t Position = 0;\r
226 int How = SEEK_SET;\r
227\r
228\r
229 if((offset != NULL) || (filp->Oflags & O_APPEND)) {\r
230 if(filp->Oflags & O_APPEND) {\r
231 Position = 0;\r
232 How = SEEK_END;\r
233 }\r
234 else {\r
235 Position = *offset;\r
236 How = SEEK_SET;\r
237 }\r
238 BufSize = (ssize_t)da_ShellSeek(filp, Position, How);\r
239 if(BufSize >= 0) {\r
240 filp->f_offset = BufSize;\r
241 }\r
242 }\r
243\r
244 BufSize = (ssize_t)BufferSize;\r
245 FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
246\r
247 Status = ShellWriteFile( FileHandle, (UINTN *)&BufSize, (void *)Buffer);\r
248\r
249 if(Status != RETURN_SUCCESS) {\r
250 EFIerrno = Status;\r
251 errno = EFI2errno(Status);\r
252 if(Status == EFI_UNSUPPORTED) {\r
253 errno = EISDIR;\r
254 }\r
255 BufSize = -1;\r
256 }\r
257 else {\r
258 filp->f_offset += BufSize; // Advance to where we want to write next.\r
259 }\r
260\r
261 return BufSize;\r
262}\r
263\r
264static\r
265int\r
266EFIAPI\r
267da_ShellStat(\r
268 struct __filedes *filp,\r
269 struct stat *statbuf,\r
270 void *Something\r
271 )\r
272{\r
273 SHELL_FILE_HANDLE FileHandle;\r
274 EFI_FILE_INFO *FileInfo = NULL;\r
275 UINT64 Attributes;\r
276 RETURN_STATUS Status;\r
277 mode_t newmode;\r
278\r
279 FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
280\r
281 FileInfo = ShellGetFileInfo( FileHandle);\r
282\r
283 if(FileInfo != NULL) {\r
284 // Got the info, now populate statbuf with it\r
285 statbuf->st_blksize = S_BLKSIZE;\r
286 statbuf->st_size = FileInfo->FileSize;\r
287 statbuf->st_physsize = FileInfo->PhysicalSize;\r
288 statbuf->st_birthtime = Efi2Time( &FileInfo->CreateTime);\r
289 statbuf->st_atime = Efi2Time( &FileInfo->LastAccessTime);\r
290 statbuf->st_mtime = Efi2Time( &FileInfo->ModificationTime);\r
291 Attributes = FileInfo->Attribute;\r
292 newmode = (mode_t)(Attributes << S_EFISHIFT) | S_ACC_READ;\r
293 if((Attributes & EFI_FILE_DIRECTORY) == 0) {\r
294 newmode |= _S_IFREG;\r
295 if((Attributes & EFI_FILE_READ_ONLY) == 0) {\r
296 newmode |= S_ACC_WRITE;\r
297 }\r
298 }\r
299 else {\r
300 newmode |= _S_IFDIR;\r
301 }\r
302 statbuf->st_mode = newmode;\r
303 Status = RETURN_SUCCESS;\r
304 }\r
305 else {\r
306 Status = RETURN_DEVICE_ERROR;\r
41b152c5 307 errno = EIO;\r
53e1e5c6 308 }\r
53e1e5c6 309 EFIerrno = Status;\r
310\r
311 if(FileInfo != NULL) {\r
312 FreePool(FileInfo); // Release the buffer allocated by the GetInfo function\r
313 }\r
41b152c5 314 return (Status == RETURN_SUCCESS)? 0 : -1;\r
53e1e5c6 315}\r
316\r
317static\r
318int\r
319EFIAPI\r
320da_ShellIoctl(\r
321 struct __filedes *filp,\r
322 ULONGN cmd,\r
76beedc0 323 va_list argp\r
53e1e5c6 324 )\r
325{\r
d7ce7006 326 return -EPERM;\r
53e1e5c6 327}\r
328\r
329/** Open an abstract Shell File.\r
330**/\r
331int\r
332EFIAPI\r
333da_ShellOpen(\r
d7ce7006 334 DeviceNode *DevNode,\r
53e1e5c6 335 struct __filedes *filp,\r
d7ce7006 336 int DevInstance, /* Not used by Shell */\r
53e1e5c6 337 wchar_t *Path,\r
d7ce7006 338 wchar_t *MPath\r
53e1e5c6 339 )\r
340{\r
341 UINT64 OpenMode;\r
342 UINT64 Attributes;\r
343 SHELL_FILE_HANDLE FileHandle;\r
344 GenericInstance *Gip;\r
345 char *NPath;\r
d7ce7006 346 wchar_t *WPath;\r
53e1e5c6 347 RETURN_STATUS Status;\r
348 int oflags;\r
d7ce7006 349 int retval;\r
53e1e5c6 350\r
351 EFIerrno = RETURN_SUCCESS;\r
352\r
353 //Attributes = Omode2EFI(mode);\r
354 Attributes = 0;\r
355\r
356 // Convert oflags to Attributes\r
357 oflags = filp->Oflags;\r
358 OpenMode = Oflags2EFI(oflags);\r
359 if(OpenMode == 0) {\r
360 errno = EINVAL;\r
361 return -1;\r
362 }\r
363\r
d7ce7006 364 /* Re-create the full mapped path for the shell. */\r
365 if(MPath != NULL) {\r
366 WPath = AllocateZeroPool(PATH_MAX * sizeof(wchar_t) + 1);\r
367 if(WPath == NULL) {\r
368 errno = ENOMEM;\r
369 EFIerrno = RETURN_OUT_OF_RESOURCES;\r
370 return -1;\r
371 }\r
372 wcsncpy(WPath, MPath, NAME_MAX); /* Get the Map Name */\r
373 wcsncat(WPath, Path, (PATH_MAX - NAME_MAX)); /* Append the path */\r
374 }\r
375 else {\r
376 WPath = Path;\r
377 }\r
378\r
379 retval = -1; /* Initially assume failure. */\r
380\r
53e1e5c6 381 /* Do we care if the file already exists?\r
382 If O_TRUNC, then delete the file. It will be created anew subsequently.\r
383 If O_EXCL, then error if the file exists and O_CREAT is set.\r
384\r
385 !!!!!!!!! Change this to use ShellSetFileInfo() to actually truncate the file\r
386 !!!!!!!!! instead of deleting and re-creating it.\r
387 */\r
d7ce7006 388 do { /* Do fake exception handling */\r
53e1e5c6 389 if((oflags & O_TRUNC) || ((oflags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))) {\r
d7ce7006 390 Status = ShellIsFile( WPath );\r
53e1e5c6 391 if(Status == RETURN_SUCCESS) {\r
392 // The file exists\r
393 if(oflags & O_TRUNC) {\r
d7ce7006 394 NPath = AllocateZeroPool(PATH_MAX);\r
53e1e5c6 395 if(NPath == NULL) {\r
396 errno = ENOMEM;\r
397 EFIerrno = RETURN_OUT_OF_RESOURCES;\r
d7ce7006 398 break;\r
53e1e5c6 399 }\r
d7ce7006 400 wcstombs(NPath, WPath, PATH_MAX);\r
53e1e5c6 401 // We do a truncate by deleting the existing file and creating a new one.\r
402 if(unlink(NPath) != 0) {\r
403 filp->f_iflags = 0; // Release our reservation on this FD\r
404 FreePool(NPath);\r
d7ce7006 405 break;\r
53e1e5c6 406 }\r
407 FreePool(NPath);\r
408 }\r
409 else if((oflags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) {\r
410 errno = EEXIST;\r
411 EFIerrno = RETURN_ACCESS_DENIED;\r
412 filp->f_iflags = 0; // Release our reservation on this FD\r
d7ce7006 413 break;\r
53e1e5c6 414 }\r
415 }\r
416 }\r
417\r
418 // Call the EFI Shell's Open function\r
d7ce7006 419 Status = ShellOpenFileByName( WPath, &FileHandle, OpenMode, Attributes);\r
53e1e5c6 420 if(RETURN_ERROR(Status)) {\r
421 filp->f_iflags = 0; // Release our reservation on this FD\r
422 // Set errno based upon Status\r
423 errno = EFI2errno(Status);\r
424 EFIerrno = Status;\r
d7ce7006 425 break;\r
53e1e5c6 426 }\r
d7ce7006 427 retval = 0;\r
53e1e5c6 428 // Successfully got a regular File\r
429 filp->f_iflags |= S_IFREG;\r
430\r
431 // Update the info in the fd\r
432 filp->devdata = (void *)FileHandle;\r
433\r
d7ce7006 434 Gip = (GenericInstance *)DevNode->InstanceList;\r
53e1e5c6 435 filp->f_offset = 0;\r
436 filp->f_ops = &Gip->Abstraction;\r
d7ce7006 437 // filp->devdata = FileHandle;\r
438 } while(FALSE);\r
53e1e5c6 439\r
d7ce7006 440 /* If we get this far, WPath is not NULL.\r
441 If MPath is not NULL, then WPath was allocated so we need to free it.\r
442 */\r
443 if(MPath != NULL) {\r
444 FreePool(WPath);\r
445 }\r
446 return retval;\r
53e1e5c6 447}\r
448\r
449#include <sys/poll.h>\r
450/* Returns a bit mask describing which operations could be completed immediately.\r
451\r
452 For now, assume the file system, via the shell, is always ready.\r
453\r
454 (POLLIN | POLLRDNORM) The file system is ready to be read.\r
455 (POLLOUT) The file system is ready for output.\r
456\r
457*/\r
458static\r
459short\r
460EFIAPI\r
461da_ShellPoll(\r
462 struct __filedes *filp,\r
463 short events\r
464 )\r
465{\r
466 UINT32 RdyMask;\r
467 short retval = 0;\r
468\r
469 RdyMask = (UINT32)filp->Oflags;\r
470\r
471 switch(RdyMask & O_ACCMODE) {\r
472 case O_RDONLY:\r
473 retval = (POLLIN | POLLRDNORM);\r
474 break;\r
475\r
476 case O_WRONLY:\r
477 retval = POLLOUT;\r
478 break;\r
479\r
480 case O_RDWR:\r
481 retval = (POLLIN | POLLRDNORM | POLLOUT);\r
482 break;\r
483\r
484 default:\r
485 retval = POLLERR;\r
486 break;\r
487 }\r
488 return (retval & (events | POLL_RETONLY));\r
489}\r
490\r
491static\r
492int\r
493EFIAPI\r
494da_ShellRename(\r
495 const char *from,\r
496 const char *to\r
497 )\r
498{\r
499 RETURN_STATUS Status;\r
500 EFI_FILE_INFO *NewFileInfo;\r
501 EFI_FILE_INFO *OldFileInfo;\r
d7ce7006 502 wchar_t *NewFn;\r
53e1e5c6 503 int OldFd;\r
504 SHELL_FILE_HANDLE FileHandle;\r
d7ce7006 505 wchar_t *NormalizedPath;\r
53e1e5c6 506\r
507 // Open old file\r
508 OldFd = open(from, O_RDWR, 0);\r
509 if(OldFd >= 0) {\r
510 FileHandle = (SHELL_FILE_HANDLE)gMD->fdarray[OldFd].devdata;\r
511\r
512 NewFileInfo = malloc(sizeof(EFI_FILE_INFO) + PATH_MAX);\r
513 if(NewFileInfo != NULL) {\r
514 OldFileInfo = ShellGetFileInfo( FileHandle);\r
515 if(OldFileInfo != NULL) {\r
516 // Copy the Old file info into our new buffer, and free the old.\r
d7ce7006 517 memcpy(NewFileInfo, OldFileInfo, sizeof(EFI_FILE_INFO));\r
53e1e5c6 518 FreePool(OldFileInfo);\r
d7ce7006 519 // Normalize path and convert to WCS.\r
520 NormalizedPath = NormalizePath(to);\r
521 if (NormalizedPath != NULL) {\r
53e1e5c6 522 // Strip off all but the file name portion of new\r
d7ce7006 523 NewFn = GetFileNameFromPath(NormalizedPath);\r
53e1e5c6 524 // Copy the new file name into our new file info buffer\r
d7ce7006 525 wcsncpy(NewFileInfo->FileName, NewFn, wcslen(NewFn) + 1);\r
526 // Update the size of the structure.\r
527 NewFileInfo->Size = sizeof(EFI_FILE_INFO) + StrSize(NewFn);\r
53e1e5c6 528 // Apply the new file name\r
529 Status = ShellSetFileInfo(FileHandle, NewFileInfo);\r
d7ce7006 530 free(NormalizedPath);\r
53e1e5c6 531 free(NewFileInfo);\r
532 if(Status == EFI_SUCCESS) {\r
533 // File has been successfully renamed. We are DONE!\r
534 return 0;\r
535 }\r
536 errno = EFI2errno( Status );\r
537 EFIerrno = Status;\r
538 }\r
539 else {\r
d7ce7006 540 free(NewFileInfo);\r
541 errno = ENOMEM;\r
542 }\r
543 }\r
544 else {\r
545 free(NewFileInfo);\r
53e1e5c6 546 errno = EIO;\r
547 }\r
548 }\r
549 else {\r
550 errno = ENOMEM;\r
551 }\r
552 }\r
553 return -1;\r
554}\r
555\r
556static\r
557int\r
558EFIAPI\r
559da_ShellRmdir(\r
560 struct __filedes *filp\r
561 )\r
562{\r
563 SHELL_FILE_HANDLE FileHandle;\r
564 RETURN_STATUS Status = RETURN_SUCCESS;\r
565 EFI_FILE_INFO *FileInfo = NULL;\r
566 int Count = 0;\r
567 BOOLEAN NoFile = FALSE;\r
568\r
569 errno = 0; // Make it easier to see if we have an error later\r
570\r
571 FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
572\r
573 FileInfo = ShellGetFileInfo(FileHandle);\r
574 if(FileInfo != NULL) {\r
575 if((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {\r
576 errno = ENOTDIR;\r
577 }\r
578 else {\r
579 // See if the directory has any entries other than ".." and ".".\r
580 FreePool(FileInfo); // Free up the buffer from ShellGetFileInfo()\r
581 Status = ShellFindFirstFile( FileHandle, &FileInfo);\r
582 if(Status == RETURN_SUCCESS) {\r
583 ++Count;\r
584 while(Count < 3) {\r
585 Status = ShellFindNextFile( FileHandle, FileInfo, &NoFile);\r
586 if(Status == RETURN_SUCCESS) {\r
587 if(NoFile) {\r
588 break;\r
589 }\r
590 ++Count;\r
591 }\r
592 else {\r
593 Count = 99;\r
594 }\r
595 }\r
596 FreePool(FileInfo); // Free buffer from ShellFindFirstFile()\r
597 if(Count < 3) {\r
598 // Directory is empty\r
599 Status = ShellDeleteFile( &FileHandle);\r
600 if(Status == RETURN_SUCCESS) {\r
601 EFIerrno = RETURN_SUCCESS;\r
602 return 0;\r
603 /* ######## SUCCESSFUL RETURN ######## */\r
604 }\r
605 }\r
606 else {\r
607 if(Count == 99) {\r
608 errno = EIO;\r
609 }\r
610 else {\r
611 errno = ENOTEMPTY;\r
612 }\r
613 }\r
614 }\r
615 }\r
616 }\r
617 else {\r
618 errno = EIO;\r
619 }\r
620 EFIerrno = Status;\r
621 if(errno == 0) {\r
622 errno = EFI2errno( Status );\r
623 }\r
624 return -1;\r
625}\r
626\r
627/** Construct an instance of the abstract Shell device.\r
628\r
629 Allocate the instance structure and populate it with the information for\r
630 the device.\r
631**/\r
632RETURN_STATUS\r
633EFIAPI\r
634__ctor_DevShell(\r
635 IN EFI_HANDLE ImageHandle,\r
636 IN EFI_SYSTEM_TABLE *SystemTable\r
637)\r
638{\r
639 GenericInstance *Stream;\r
640 DeviceNode *Node;\r
641 RETURN_STATUS Status;\r
642\r
643 Stream = (GenericInstance *)AllocateZeroPool(sizeof(GenericInstance));\r
644 if(Stream == NULL) {\r
645 return RETURN_OUT_OF_RESOURCES;\r
646 }\r
647\r
648 Stream->Cookie = CON_COOKIE;\r
649 Stream->InstanceNum = 1;\r
650 Stream->Dev = NULL;\r
651 Stream->Abstraction.fo_close = &da_ShellClose;\r
652 Stream->Abstraction.fo_read = &da_ShellRead;\r
653 Stream->Abstraction.fo_write = &da_ShellWrite;\r
654 Stream->Abstraction.fo_fcntl = &fnullop_fcntl;\r
655 Stream->Abstraction.fo_poll = &da_ShellPoll;\r
656 Stream->Abstraction.fo_flush = &fnullop_flush;\r
657 Stream->Abstraction.fo_stat = &da_ShellStat;\r
d7ce7006 658 Stream->Abstraction.fo_ioctl = &da_ShellIoctl;\r
53e1e5c6 659 Stream->Abstraction.fo_delete = &da_ShellDelete;\r
660 Stream->Abstraction.fo_rmdir = &da_ShellRmdir;\r
661 Stream->Abstraction.fo_mkdir = &da_ShellMkdir;\r
662 Stream->Abstraction.fo_rename = &da_ShellRename;\r
663 Stream->Abstraction.fo_lseek = &da_ShellSeek;\r
664\r
665 Node = __DevRegister(NULL, NULL, &da_ShellOpen, Stream, 1, sizeof(GenericInstance), O_RDWR);\r
666 Status = EFIerrno;\r
667 Stream->Parent = Node;\r
668\r
669 return Status;\r
670}\r
671\r
672RETURN_STATUS\r
673EFIAPI\r
674__dtor_DevShell(\r
675 IN EFI_HANDLE ImageHandle,\r
676 IN EFI_SYSTEM_TABLE *SystemTable\r
677)\r
678{\r
679 if(daDefaultDevice != NULL) {\r
680 if(daDefaultDevice->InstanceList != NULL) {\r
681 FreePool(daDefaultDevice->InstanceList);\r
682 }\r
683 FreePool(daDefaultDevice);\r
684 }\r
685 return RETURN_SUCCESS;\r
686}\r