2 Support a Semi Host file system over a debuggers JTAG
4 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Guid/FileInfo.h>
19 #include <Guid/FileSystemInfo.h>
21 #include <Library/BaseLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/SemihostLib.h>
26 #include <Library/UefiBootServicesTableLib.h>
27 #include <Library/UefiLib.h>
29 #include <Protocol/DevicePath.h>
30 #include <Protocol/SimpleFileSystem.h>
32 #include "SemihostFs.h"
35 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs
= {
36 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
,
40 EFI_FILE gSemihostFsFile
= {
41 EFI_FILE_PROTOCOL_REVISION
,
55 // Device path for SemiHosting. It contains our autogened Caller ID GUID.
58 VENDOR_DEVICE_PATH Guid
;
59 EFI_DEVICE_PATH_PROTOCOL End
;
60 } SEMIHOST_DEVICE_PATH
;
62 SEMIHOST_DEVICE_PATH gDevicePath
= {
64 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, sizeof (VENDOR_DEVICE_PATH
), 0 },
67 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0}
76 UINT32 SemihostHandle
;
80 #define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' )
81 #define SEMIHOST_FCB_FROM_THIS(a) CR(a, SEMIHOST_FCB, File, SEMIHOST_FCB_SIGNATURE)
82 #define SEMIHOST_FCB_FROM_LINK(a) CR(a, SEMIHOST_FCB, Link, SEMIHOST_FCB_SIGNATURE);
84 EFI_HANDLE gInstallHandle
= NULL
;
85 LIST_ENTRY gFileList
= INITIALIZE_LIST_HEAD_VARIABLE (gFileList
);
92 SEMIHOST_FCB
*Fcb
= AllocateZeroPool (sizeof (SEMIHOST_FCB
));
95 CopyMem (&Fcb
->File
, &gSemihostFsFile
, sizeof (gSemihostFsFile
));
96 Fcb
->Signature
= SEMIHOST_FCB_SIGNATURE
;
107 // Remove Fcb from gFileList.
108 RemoveEntryList (&Fcb
->Link
);
110 // To help debugging...
120 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*This
,
124 SEMIHOST_FCB
*RootFcb
= NULL
;
127 return EFI_INVALID_PARAMETER
;
130 RootFcb
= AllocateFCB ();
131 if (RootFcb
== NULL
) {
132 return EFI_OUT_OF_RESOURCES
;
135 RootFcb
->IsRoot
= TRUE
;
137 InsertTailList (&gFileList
, &RootFcb
->Link
);
139 *Root
= &RootFcb
->File
;
147 OUT EFI_FILE
**NewHandle
,
153 SEMIHOST_FCB
*FileFcb
= NULL
;
154 EFI_STATUS Status
= EFI_SUCCESS
;
155 UINT32 SemihostHandle
;
156 CHAR8
*AsciiFileName
;
162 if ((FileName
== NULL
) || (NewHandle
== NULL
)) {
163 return EFI_INVALID_PARAMETER
;
166 // Semihost interface requires ASCII filesnames
167 Length
= StrSize (FileName
);
169 AsciiFileName
= AllocatePool (Length
);
170 if (AsciiFileName
== NULL
) {
171 return EFI_OUT_OF_RESOURCES
;
174 AsciiPtr
= AsciiFileName
;
177 *AsciiPtr
++ = *FileName
++ & 0xFF;
180 if ((AsciiStrCmp (AsciiFileName
, "\\") == 0) || (AsciiStrCmp (AsciiFileName
, "/") == 0) || (AsciiStrCmp (AsciiFileName
, "") == 0)) {
181 // Opening '/', '\', or the NULL pathname is trying to open the root directory
184 // Root directory node doesn't have a name.
185 FreePool (AsciiFileName
);
186 AsciiFileName
= NULL
;
188 // Translate EFI_FILE_MODE into Semihosting mode
189 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
190 SemihostMode
= SEMIHOST_FILE_MODE_WRITE
| SEMIHOST_FILE_MODE_BINARY
;
191 } else if (OpenMode
& EFI_FILE_MODE_READ
) {
192 SemihostMode
= SEMIHOST_FILE_MODE_READ
| SEMIHOST_FILE_MODE_BINARY
;
194 return EFI_UNSUPPORTED
;
197 // Add the creation flag if necessary
198 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
199 SemihostMode
|= SEMIHOST_FILE_MODE_CREATE
;
202 // Call the semihosting interface to open the file.
203 Status
= SemihostFileOpen (AsciiFileName
, SemihostMode
, &SemihostHandle
);
204 if (EFI_ERROR(Status
)) {
211 // Allocate a control block and fill it
212 FileFcb
= AllocateFCB ();
213 if (FileFcb
== NULL
) {
214 return EFI_OUT_OF_RESOURCES
;
217 FileFcb
->FileName
= AsciiFileName
;
218 FileFcb
->SemihostHandle
= SemihostHandle
;
219 FileFcb
->Position
= 0;
220 FileFcb
->IsRoot
= IsRoot
;
222 InsertTailList (&gFileList
, &FileFcb
->Link
);
224 *NewHandle
= &FileFcb
->File
;
235 SEMIHOST_FCB
*Fcb
= NULL
;
236 EFI_STATUS Status
= EFI_SUCCESS
;
238 Fcb
= SEMIHOST_FCB_FROM_THIS(File
);
240 if (Fcb
->IsRoot
== TRUE
) {
242 Status
= EFI_SUCCESS
;
244 Status
= SemihostFileClose (Fcb
->SemihostHandle
);
245 if (!EFI_ERROR(Status
)) {
246 FreePool (Fcb
->FileName
);
259 SEMIHOST_FCB
*Fcb
= NULL
;
264 Fcb
= SEMIHOST_FCB_FROM_THIS(File
);
266 // Get the filename from the Fcb
267 NameSize
= AsciiStrLen (Fcb
->FileName
);
268 FileName
= AllocatePool (NameSize
+ 1);
270 AsciiStrCpy (FileName
, Fcb
->FileName
);
272 // Close the file if it's open. Disregard return status,
273 // since it might give an error if the file isn't open.
276 // Call the semihost interface to delete the file.
277 Status
= SemihostFileRemove (FileName
);
285 IN OUT UINTN
*BufferSize
,
289 SEMIHOST_FCB
*Fcb
= NULL
;
292 Fcb
= SEMIHOST_FCB_FROM_THIS(File
);
294 if (Fcb
->IsRoot
== TRUE
) {
295 Status
= EFI_UNSUPPORTED
;
297 Status
= SemihostFileRead (Fcb
->SemihostHandle
, BufferSize
, Buffer
);
298 if (!EFI_ERROR (Status
)) {
299 Fcb
->Position
+= *BufferSize
;
309 IN OUT UINTN
*BufferSize
,
313 SEMIHOST_FCB
*Fcb
= NULL
;
315 UINTN WriteSize
= *BufferSize
;
317 Fcb
= SEMIHOST_FCB_FROM_THIS(File
);
319 Status
= SemihostFileWrite (Fcb
->SemihostHandle
, &WriteSize
, Buffer
);
321 if (!EFI_ERROR(Status
)) {
322 // Semihost write return the number of bytes *NOT* written.
323 *BufferSize
-= WriteSize
;
324 Fcb
->Position
+= *BufferSize
;
336 SEMIHOST_FCB
*Fcb
= NULL
;
338 if (Position
== NULL
) {
339 return EFI_INVALID_PARAMETER
;
342 Fcb
= SEMIHOST_FCB_FROM_THIS(File
);
344 *Position
= Fcb
->Position
;
355 SEMIHOST_FCB
*Fcb
= NULL
;
359 Fcb
= SEMIHOST_FCB_FROM_THIS(File
);
361 Status
= SemihostFileLength (Fcb
->SemihostHandle
, &Length
);
362 if (!EFI_ERROR(Status
) && (Length
< Position
)) {
366 Status
= SemihostFileSeek (Fcb
->SemihostHandle
, (UINT32
)Position
);
367 if (!EFI_ERROR(Status
)) {
368 Fcb
->Position
= Position
;
377 IN SEMIHOST_FCB
*Fcb
,
378 IN OUT UINTN
*BufferSize
,
382 EFI_FILE_INFO
*Info
= NULL
;
389 if (Fcb
->IsRoot
== TRUE
) {
390 ResultSize
= SIZE_OF_EFI_FILE_INFO
+ sizeof(CHAR16
);
392 NameSize
= AsciiStrLen (Fcb
->FileName
) + 1;
393 ResultSize
= SIZE_OF_EFI_FILE_INFO
+ NameSize
* sizeof (CHAR16
);
396 if (*BufferSize
< ResultSize
) {
397 *BufferSize
= ResultSize
;
398 return EFI_BUFFER_TOO_SMALL
;
403 // Zero out the structure
404 ZeroMem (Info
, SIZE_OF_EFI_FILE_INFO
);
406 // Fill in the structure
407 Info
->Size
= ResultSize
;
409 if (Fcb
->IsRoot
== TRUE
) {
410 Info
->Attribute
= EFI_FILE_READ_ONLY
| EFI_FILE_DIRECTORY
;
411 Info
->FileName
[0] = L
'\0';
413 Status
= SemihostFileLength (Fcb
->SemihostHandle
, &Length
);
414 if (EFI_ERROR(Status
)) {
418 Info
->FileSize
= Length
;
419 Info
->PhysicalSize
= Length
;
421 for (Index
= 0; Index
< NameSize
; Index
++) {
422 Info
->FileName
[Index
] = Fcb
->FileName
[Index
];
427 *BufferSize
= ResultSize
;
435 IN SEMIHOST_FCB
*Fcb
,
436 IN OUT UINTN
*BufferSize
,
440 EFI_FILE_SYSTEM_INFO
*Info
= NULL
;
442 STATIC CHAR16 Label
[] = L
"SemihostFs";
443 UINTN ResultSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize(Label
);
445 if(*BufferSize
>= ResultSize
) {
446 ZeroMem (Buffer
, ResultSize
);
447 Status
= EFI_SUCCESS
;
451 Info
->Size
= ResultSize
;
452 Info
->ReadOnly
= FALSE
;
453 Info
->VolumeSize
= 0;
457 StrCpy (Info
->VolumeLabel
, Label
);
459 Status
= EFI_BUFFER_TOO_SMALL
;
462 *BufferSize
= ResultSize
;
469 IN EFI_GUID
*InformationType
,
470 IN OUT UINTN
*BufferSize
,
474 SEMIHOST_FCB
*Fcb
= NULL
;
475 EFI_STATUS Status
= EFI_UNSUPPORTED
;
477 Fcb
= SEMIHOST_FCB_FROM_THIS(File
);
479 if (CompareGuid(InformationType
, &gEfiFileSystemInfoGuid
) != 0) {
480 Status
= GetFilesystemInfo(Fcb
, BufferSize
, Buffer
);
481 } else if (CompareGuid(InformationType
, &gEfiFileInfoGuid
) != 0) {
482 Status
= GetFileInfo(Fcb
, BufferSize
, Buffer
);
491 IN EFI_GUID
*InformationType
,
496 return EFI_UNSUPPORTED
;
508 SemihostFsEntryPoint (
509 IN EFI_HANDLE ImageHandle
,
510 IN EFI_SYSTEM_TABLE
*SystemTable
513 EFI_STATUS Status
= EFI_NOT_FOUND
;
515 if (SemihostConnectionSupported ()) {
516 Status
= gBS
->InstallMultipleProtocolInterfaces (
518 &gEfiSimpleFileSystemProtocolGuid
, &gSemihostFs
,
519 &gEfiDevicePathProtocolGuid
, &gDevicePath
,