diff options
author | AJFISH <AJFISH@6f19259b-4bc3-4df7-8a09-765794883524> | 2009-12-06 01:57:05 +0000 |
---|---|---|
committer | AJFISH <AJFISH@6f19259b-4bc3-4df7-8a09-765794883524> | 2009-12-06 01:57:05 +0000 |
commit | 2ef2b01e07c02db339f34004445734a2dbdd80e1 (patch) | |
tree | 19532a6be8d8bdb0aef04bd00c1efb582f6dc841 /ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c | |
parent | f7753a96ba1653ddd31b01c198a352f6332ac404 (diff) | |
download | edk2-platforms-2ef2b01e07c02db339f34004445734a2dbdd80e1.tar.xz |
Adding support for BeagleBoard.
ArmPkg - Supoprt for ARM specific things that can change as the architecture changes. Plus semihosting JTAG drivers.
EmbeddedPkg - Generic support for an embeddded platform. Including a light weight command line shell.
BeagleBoardPkg - Platform specifics for BeagleBoard. SD Card works, but USB has issues. Looks like a bug in the open source USB stack (Our internal stack works fine).
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9518 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c')
-rw-r--r-- | ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c new file mode 100644 index 0000000000..0f1da65ba0 --- /dev/null +++ b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c @@ -0,0 +1,526 @@ +/** @file
+ Support a Semi Host file system over a debuggers JTAG
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SemihostLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include "SemihostFs.h"
+
+
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs = {
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
+ VolumeOpen
+};
+
+EFI_FILE gSemihostFsFile = {
+ EFI_FILE_PROTOCOL_REVISION,
+ FileOpen,
+ FileClose,
+ FileDelete,
+ FileRead,
+ FileWrite,
+ FileGetPosition,
+ FileSetPosition,
+ FileGetInfo,
+ FileSetInfo,
+ FileFlush
+};
+
+//
+// Device path for SemiHosting. It contains our autogened Caller ID GUID.
+//
+typedef struct {
+ VENDOR_DEVICE_PATH Guid;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} SEMIHOST_DEVICE_PATH;
+
+SEMIHOST_DEVICE_PATH gDevicePath = {
+ {
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0 },
+ EFI_CALLER_ID_GUID
+ },
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}
+};
+
+typedef struct {
+ LIST_ENTRY Link;
+ UINT64 Signature;
+ EFI_FILE File;
+ CHAR8 *FileName;
+ UINT32 Position;
+ UINT32 SemihostHandle;
+ BOOLEAN IsRoot;
+} SEMIHOST_FCB;
+
+#define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' )
+#define SEMIHOST_FCB_FROM_THIS(a) CR(a, SEMIHOST_FCB, File, SEMIHOST_FCB_SIGNATURE)
+#define SEMIHOST_FCB_FROM_LINK(a) CR(a, SEMIHOST_FCB, Link, SEMIHOST_FCB_SIGNATURE);
+
+EFI_HANDLE gInstallHandle = NULL;
+LIST_ENTRY gFileList = INITIALIZE_LIST_HEAD_VARIABLE (gFileList);
+
+SEMIHOST_FCB *
+AllocateFCB (
+ VOID
+ )
+{
+ SEMIHOST_FCB *Fcb = AllocateZeroPool (sizeof (SEMIHOST_FCB));
+
+ if (Fcb != NULL) {
+ CopyMem (&Fcb->File, &gSemihostFsFile, sizeof (gSemihostFsFile));
+ Fcb->Signature = SEMIHOST_FCB_SIGNATURE;
+ }
+
+ return Fcb;
+}
+
+VOID
+FreeFCB (
+ IN SEMIHOST_FCB *Fcb
+ )
+{
+ // Remove Fcb from gFileList.
+ RemoveEntryList (&Fcb->Link);
+
+ // To help debugging...
+ Fcb->Signature = 0;
+
+ FreePool (Fcb);
+}
+
+
+
+EFI_STATUS
+VolumeOpen (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE **Root
+ )
+{
+ SEMIHOST_FCB *RootFcb = NULL;
+
+ if (Root == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RootFcb = AllocateFCB ();
+ if (RootFcb == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RootFcb->IsRoot = TRUE;
+
+ InsertTailList (&gFileList, &RootFcb->Link);
+
+ *Root = &RootFcb->File;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FileOpen (
+ IN EFI_FILE *File,
+ OUT EFI_FILE **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ SEMIHOST_FCB *FileFcb = NULL;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 SemihostHandle;
+ CHAR8 *AsciiFileName;
+ CHAR8 *AsciiPtr;
+ UINTN Length;
+ UINT32 SemihostMode;
+ BOOLEAN IsRoot;
+
+ if ((FileName == NULL) || (NewHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Semihost interface requires ASCII filesnames
+ Length = StrSize (FileName);
+
+ AsciiFileName = AllocatePool (Length);
+ if (AsciiFileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AsciiPtr = AsciiFileName;
+
+ while (Length--) {
+ *AsciiPtr++ = *FileName++ & 0xFF;
+ }
+
+ if ((AsciiStrCmp (AsciiFileName, "\\") == 0) || (AsciiStrCmp (AsciiFileName, "/") == 0) || (AsciiStrCmp (AsciiFileName, "") == 0)) {
+ // Opening '/', '\', or the NULL pathname is trying to open the root directory
+ IsRoot = TRUE;
+
+ // Root directory node doesn't have a name.
+ FreePool (AsciiFileName);
+ AsciiFileName = NULL;
+ } else {
+ // Translate EFI_FILE_MODE into Semihosting mode
+ if (OpenMode & EFI_FILE_MODE_WRITE) {
+ SemihostMode = SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY;
+ } else if (OpenMode & EFI_FILE_MODE_READ) {
+ SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ // Add the creation flag if necessary
+ if (OpenMode & EFI_FILE_MODE_CREATE) {
+ SemihostMode |= SEMIHOST_FILE_MODE_CREATE;
+ }
+
+ // Call the semihosting interface to open the file.
+ Status = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ IsRoot = FALSE;
+ }
+
+ // Allocate a control block and fill it
+ FileFcb = AllocateFCB ();
+ if (FileFcb == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileFcb->FileName = AsciiFileName;
+ FileFcb->SemihostHandle = SemihostHandle;
+ FileFcb->Position = 0;
+ FileFcb->IsRoot = IsRoot;
+
+ InsertTailList (&gFileList, &FileFcb->Link);
+
+ *NewHandle = &FileFcb->File;
+
+ return Status;
+}
+
+
+EFI_STATUS
+FileClose (
+ IN EFI_FILE *File
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ if (Fcb->IsRoot == TRUE) {
+ FreeFCB (Fcb);
+ Status = EFI_SUCCESS;
+ } else {
+ Status = SemihostFileClose (Fcb->SemihostHandle);
+ if (!EFI_ERROR(Status)) {
+ FreePool (Fcb->FileName);
+ FreeFCB (Fcb);
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FileDelete (
+ IN EFI_FILE *File
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ EFI_STATUS Status;
+ CHAR8 *FileName;
+ UINTN NameSize;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ // Get the filename from the Fcb
+ NameSize = AsciiStrLen (Fcb->FileName);
+ FileName = AllocatePool (NameSize + 1);
+
+ AsciiStrCpy (FileName, Fcb->FileName);
+
+ // Close the file if it's open. Disregard return status,
+ // since it might give an error if the file isn't open.
+ File->Close (File);
+
+ // Call the semihost interface to delete the file.
+ Status = SemihostFileRemove (FileName);
+
+ return Status;
+}
+
+EFI_STATUS
+FileRead (
+ IN EFI_FILE *File,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ EFI_STATUS Status;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ if (Fcb->IsRoot == TRUE) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ Status = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);
+ if (!EFI_ERROR (Status)) {
+ Fcb->Position += *BufferSize;
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FileWrite (
+ IN EFI_FILE *File,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ EFI_STATUS Status;
+ UINTN WriteSize = *BufferSize;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);
+
+ if (!EFI_ERROR(Status)) {
+ // Semihost write return the number of bytes *NOT* written.
+ *BufferSize -= WriteSize;
+ Fcb->Position += *BufferSize;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FileGetPosition (
+ IN EFI_FILE *File,
+ OUT UINT64 *Position
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+
+ if (Position == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ *Position = Fcb->Position;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FileSetPosition (
+ IN EFI_FILE *File,
+ IN UINT64 Position
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ UINT32 Length;
+ EFI_STATUS Status;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ Status = SemihostFileLength (Fcb->SemihostHandle, &Length);
+ if (!EFI_ERROR(Status) && (Length < Position)) {
+ Position = Length;
+ }
+
+ Status = SemihostFileSeek (Fcb->SemihostHandle, (UINT32)Position);
+ if (!EFI_ERROR(Status)) {
+ Fcb->Position = Position;
+ }
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+GetFileInfo (
+ IN SEMIHOST_FCB *Fcb,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_FILE_INFO *Info = NULL;
+ UINTN NameSize = 0;
+ UINTN ResultSize;
+ UINTN Index;
+ UINT32 Length;
+ EFI_STATUS Status;
+
+ if (Fcb->IsRoot == TRUE) {
+ ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);
+ } else {
+ NameSize = AsciiStrLen (Fcb->FileName) + 1;
+ ResultSize = SIZE_OF_EFI_FILE_INFO + NameSize * sizeof (CHAR16);
+ }
+
+ if (*BufferSize < ResultSize) {
+ *BufferSize = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Info = Buffer;
+
+ // Zero out the structure
+ ZeroMem (Info, SIZE_OF_EFI_FILE_INFO);
+
+ // Fill in the structure
+ Info->Size = ResultSize;
+
+ if (Fcb->IsRoot == TRUE) {
+ Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
+ Info->FileName[0] = L'\0';
+ } else {
+ Status = SemihostFileLength (Fcb->SemihostHandle, &Length);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Info->FileSize = Length;
+ Info->PhysicalSize = Length;
+
+ for (Index = 0; Index < NameSize; Index++) {
+ Info->FileName[Index] = Fcb->FileName[Index];
+ }
+ }
+
+
+ *BufferSize = ResultSize;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+GetFilesystemInfo (
+ IN SEMIHOST_FCB *Fcb,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_FILE_SYSTEM_INFO *Info = NULL;
+ EFI_STATUS Status;
+ STATIC CHAR16 Label[] = L"SemihostFs";
+ UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(Label);
+
+ if(*BufferSize >= ResultSize) {
+ ZeroMem (Buffer, ResultSize);
+ Status = EFI_SUCCESS;
+
+ Info = Buffer;
+
+ Info->Size = ResultSize;
+ Info->ReadOnly = FALSE;
+ Info->VolumeSize = 0;
+ Info->FreeSpace = 0;
+ Info->BlockSize = 0;
+
+ StrCpy (Info->VolumeLabel, Label);
+ } else {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *BufferSize = ResultSize;
+ return Status;
+}
+
+EFI_STATUS
+FileGetInfo (
+ IN EFI_FILE *File,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ if (CompareGuid(InformationType, &gEfiFileSystemInfoGuid) != 0) {
+ Status = GetFilesystemInfo(Fcb, BufferSize, Buffer);
+ } else if (CompareGuid(InformationType, &gEfiFileInfoGuid) != 0) {
+ Status = GetFileInfo(Fcb, BufferSize, Buffer);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FileSetInfo (
+ IN EFI_FILE *File,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+FileFlush (
+ IN EFI_FILE *File
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SemihostFsEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status = EFI_NOT_FOUND;
+
+ if (SemihostConnectionSupported ()) {
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gInstallHandle,
+ &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs,
+ &gEfiDevicePathProtocolGuid, &gDevicePath,
+ NULL
+ );
+ }
+
+ return Status;
+}
+
|