diff options
Diffstat (limited to 'roms/edk2/ArmPkg/Library/SemihostLib')
5 files changed, 605 insertions, 0 deletions
diff --git a/roms/edk2/ArmPkg/Library/SemihostLib/AArch64/GccSemihost.S b/roms/edk2/ArmPkg/Library/SemihostLib/AArch64/GccSemihost.S new file mode 100644 index 000000000..a44307563 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/SemihostLib/AArch64/GccSemihost.S @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+#include <AsmMacroIoLibV8.h>
+
+ASM_FUNC(GccSemihostCall)
+ hlt #0xf000
+ ret
diff --git a/roms/edk2/ArmPkg/Library/SemihostLib/Arm/GccSemihost.S b/roms/edk2/ArmPkg/Library/SemihostLib/Arm/GccSemihost.S new file mode 100644 index 000000000..d6f81ec2c --- /dev/null +++ b/roms/edk2/ArmPkg/Library/SemihostLib/Arm/GccSemihost.S @@ -0,0 +1,31 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+#include <AsmMacroIoLib.h>
+
+/*
+ Semihosting operation request mechanism
+
+ SVC 0x123456 in ARM state (for all architectures)
+ SVC 0xAB in Thumb state (excluding ARMv7-M)
+ BKPT 0xAB for ARMv7-M (Thumb-2 only)
+
+ R0 - operation type
+ R1 - block containing all other parametes
+
+ lr - must be saved as svc instruction will cause an svc exception and write
+ the svc lr register. That happens to be the one we are using, so we must
+ save it or we will not be able to return.
+ */
+ASM_FUNC(GccSemihostCall)
+ stmfd sp!, {lr}
+ svc #0x123456
+ ldmfd sp!, {lr}
+ bx lr
+
+
diff --git a/roms/edk2/ArmPkg/Library/SemihostLib/SemihostLib.c b/roms/edk2/ArmPkg/Library/SemihostLib/SemihostLib.c new file mode 100644 index 000000000..78b862468 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/SemihostLib/SemihostLib.c @@ -0,0 +1,307 @@ +/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2013 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Base.h>
+
+#include <Library/BaseLib.h>
+#include <Library/SemihostLib.h>
+
+#include "SemihostPrivate.h"
+
+BOOLEAN
+SemihostConnectionSupported (
+ VOID
+ )
+{
+ return SEMIHOST_SUPPORTED;
+}
+
+RETURN_STATUS
+SemihostFileOpen (
+ IN CHAR8 *FileName,
+ IN UINT32 Mode,
+ OUT UINTN *FileHandle
+ )
+{
+ SEMIHOST_FILE_OPEN_BLOCK OpenBlock;
+ INT32 Result;
+
+ if (FileHandle == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ // Remove any leading separator (e.g.: '\'). EFI Shell adds one.
+ if (*FileName == '\\') {
+ FileName++;
+ }
+
+ OpenBlock.FileName = FileName;
+ OpenBlock.Mode = Mode;
+ OpenBlock.NameLength = AsciiStrLen(FileName);
+
+ Result = Semihost_SYS_OPEN(&OpenBlock);
+
+ if (Result == -1) {
+ return RETURN_NOT_FOUND;
+ } else {
+ *FileHandle = Result;
+ return RETURN_SUCCESS;
+ }
+}
+
+RETURN_STATUS
+SemihostFileSeek (
+ IN UINTN FileHandle,
+ IN UINTN Offset
+ )
+{
+ SEMIHOST_FILE_SEEK_BLOCK SeekBlock;
+ INT32 Result;
+
+ SeekBlock.Handle = FileHandle;
+ SeekBlock.Location = Offset;
+
+ Result = Semihost_SYS_SEEK(&SeekBlock);
+
+ // Semihosting does not behave as documented. It returns the offset on
+ // success.
+ if (Result < 0) {
+ return RETURN_ABORTED;
+ } else {
+ return RETURN_SUCCESS;
+ }
+}
+
+RETURN_STATUS
+SemihostFileRead (
+ IN UINTN FileHandle,
+ IN OUT UINTN *Length,
+ OUT VOID *Buffer
+ )
+{
+ SEMIHOST_FILE_READ_WRITE_BLOCK ReadBlock;
+ UINT32 Result;
+
+ if ((Length == NULL) || (Buffer == NULL)) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ ReadBlock.Handle = FileHandle;
+ ReadBlock.Buffer = Buffer;
+ ReadBlock.Length = *Length;
+
+ Result = Semihost_SYS_READ(&ReadBlock);
+
+ if ((*Length != 0) && (Result == *Length)) {
+ return RETURN_ABORTED;
+ } else {
+ *Length -= Result;
+ return RETURN_SUCCESS;
+ }
+}
+
+RETURN_STATUS
+SemihostFileWrite (
+ IN UINTN FileHandle,
+ IN OUT UINTN *Length,
+ IN VOID *Buffer
+ )
+{
+ SEMIHOST_FILE_READ_WRITE_BLOCK WriteBlock;
+
+ if ((Length == NULL) || (Buffer == NULL)) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ WriteBlock.Handle = FileHandle;
+ WriteBlock.Buffer = Buffer;
+ WriteBlock.Length = *Length;
+
+ *Length = Semihost_SYS_WRITE(&WriteBlock);
+
+ if (*Length != 0)
+ return RETURN_ABORTED;
+ else
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+SemihostFileClose (
+ IN UINTN FileHandle
+ )
+{
+ INT32 Result = Semihost_SYS_CLOSE(&FileHandle);
+
+ if (Result == -1) {
+ return RETURN_INVALID_PARAMETER;
+ } else {
+ return RETURN_SUCCESS;
+ }
+}
+
+RETURN_STATUS
+SemihostFileLength (
+ IN UINTN FileHandle,
+ OUT UINTN *Length
+ )
+{
+ INT32 Result;
+
+ if (Length == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ Result = Semihost_SYS_FLEN(&FileHandle);
+
+ if (Result == -1) {
+ return RETURN_ABORTED;
+ } else {
+ *Length = Result;
+ return RETURN_SUCCESS;
+ }
+}
+
+/**
+ Get a temporary name for a file from the host running the debug agent.
+
+ @param[out] Buffer Pointer to the buffer where the temporary name has to
+ be stored
+ @param[in] Identifier File name identifier (integer in the range 0 to 255)
+ @param[in] Length Length of the buffer to store the temporary name
+
+ @retval RETURN_SUCCESS Temporary name returned
+ @retval RETURN_INVALID_PARAMETER Invalid buffer address
+ @retval RETURN_ABORTED Temporary name not returned
+
+**/
+RETURN_STATUS
+SemihostFileTmpName(
+ OUT VOID *Buffer,
+ IN UINT8 Identifier,
+ IN UINTN Length
+ )
+{
+ SEMIHOST_FILE_TMPNAME_BLOCK TmpNameBlock;
+ INT32 Result;
+
+ if (Buffer == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ TmpNameBlock.Buffer = Buffer;
+ TmpNameBlock.Identifier = Identifier;
+ TmpNameBlock.Length = Length;
+
+ Result = Semihost_SYS_TMPNAME (&TmpNameBlock);
+
+ if (Result != 0) {
+ return RETURN_ABORTED;
+ } else {
+ return RETURN_SUCCESS;
+ }
+}
+
+RETURN_STATUS
+SemihostFileRemove (
+ IN CHAR8 *FileName
+ )
+{
+ SEMIHOST_FILE_REMOVE_BLOCK RemoveBlock;
+ UINT32 Result;
+
+ // Remove any leading separator (e.g.: '\'). EFI Shell adds one.
+ if (*FileName == '\\') {
+ FileName++;
+ }
+
+ RemoveBlock.FileName = FileName;
+ RemoveBlock.NameLength = AsciiStrLen(FileName);
+
+ Result = Semihost_SYS_REMOVE(&RemoveBlock);
+
+ if (Result == 0) {
+ return RETURN_SUCCESS;
+ } else {
+ return RETURN_ABORTED;
+ }
+}
+
+/**
+ Rename a specified file.
+
+ @param[in] FileName Name of the file to rename.
+ @param[in] NewFileName The new name of the file.
+
+ @retval RETURN_SUCCESS File Renamed
+ @retval RETURN_INVALID_PARAMETER Either the current or the new name is not specified
+ @retval RETURN_ABORTED Rename failed
+
+**/
+RETURN_STATUS
+SemihostFileRename(
+ IN CHAR8 *FileName,
+ IN CHAR8 *NewFileName
+ )
+{
+ SEMIHOST_FILE_RENAME_BLOCK RenameBlock;
+ INT32 Result;
+
+ if ((FileName == NULL) || (NewFileName == NULL)) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ RenameBlock.FileName = FileName;
+ RenameBlock.FileNameLength = AsciiStrLen (FileName);
+ RenameBlock.NewFileName = NewFileName;
+ RenameBlock.NewFileNameLength = AsciiStrLen (NewFileName);
+
+ Result = Semihost_SYS_RENAME (&RenameBlock);
+
+ if (Result != 0) {
+ return RETURN_ABORTED;
+ } else {
+ return RETURN_SUCCESS;
+ }
+}
+
+CHAR8
+SemihostReadCharacter (
+ VOID
+ )
+{
+ return Semihost_SYS_READC();
+}
+
+VOID
+SemihostWriteCharacter (
+ IN CHAR8 Character
+ )
+{
+ Semihost_SYS_WRITEC(&Character);
+}
+
+VOID
+SemihostWriteString (
+ IN CHAR8 *String
+ )
+{
+ Semihost_SYS_WRITE0(String);
+}
+
+UINT32
+SemihostSystem (
+ IN CHAR8 *CommandLine
+ )
+{
+ SEMIHOST_SYSTEM_BLOCK SystemBlock;
+
+ SystemBlock.CommandLine = CommandLine;
+ SystemBlock.CommandLength = AsciiStrLen(CommandLine);
+
+ return Semihost_SYS_SYSTEM(&SystemBlock);
+}
diff --git a/roms/edk2/ArmPkg/Library/SemihostLib/SemihostLib.inf b/roms/edk2/ArmPkg/Library/SemihostLib/SemihostLib.inf new file mode 100644 index 000000000..a46618d30 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/SemihostLib/SemihostLib.inf @@ -0,0 +1,41 @@ +#/** @file
+# Semihosting JTAG lib
+#
+# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SemihostLib
+ FILE_GUID = C40D08BA-DB7B-4F07-905A-C5FE4B5AF987
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SemihostLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = ARM AARCH64
+#
+[Sources.common]
+ SemihostLib.c
+
+[Sources.ARM]
+ Arm/GccSemihost.S | GCC
+
+[Sources.AARCH64]
+ AArch64/GccSemihost.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+
diff --git a/roms/edk2/ArmPkg/Library/SemihostLib/SemihostPrivate.h b/roms/edk2/ArmPkg/Library/SemihostLib/SemihostPrivate.h new file mode 100644 index 000000000..8d1fc6d6e --- /dev/null +++ b/roms/edk2/ArmPkg/Library/SemihostLib/SemihostPrivate.h @@ -0,0 +1,212 @@ +/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2013 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __SEMIHOST_PRIVATE_H__
+#define __SEMIHOST_PRIVATE_H__
+
+typedef struct {
+ CHAR8 *FileName;
+ UINTN Mode;
+ UINTN NameLength;
+} SEMIHOST_FILE_OPEN_BLOCK;
+
+typedef struct {
+ UINTN Handle;
+ VOID *Buffer;
+ UINTN Length;
+} SEMIHOST_FILE_READ_WRITE_BLOCK;
+
+typedef struct {
+ UINTN Handle;
+ UINTN Location;
+} SEMIHOST_FILE_SEEK_BLOCK;
+
+typedef struct {
+ VOID *Buffer;
+ UINTN Identifier;
+ UINTN Length;
+} SEMIHOST_FILE_TMPNAME_BLOCK;
+
+typedef struct {
+ CHAR8 *FileName;
+ UINTN NameLength;
+} SEMIHOST_FILE_REMOVE_BLOCK;
+
+typedef struct {
+ CHAR8 *FileName;
+ UINTN FileNameLength;
+ CHAR8 *NewFileName;
+ UINTN NewFileNameLength;
+} SEMIHOST_FILE_RENAME_BLOCK;
+
+typedef struct {
+ CHAR8 *CommandLine;
+ UINTN CommandLength;
+} SEMIHOST_SYSTEM_BLOCK;
+
+#if defined(__CC_ARM)
+
+#if defined(__thumb__)
+#define SWI 0xAB
+#else
+#define SWI 0x123456
+#endif
+
+#define SEMIHOST_SUPPORTED TRUE
+
+__swi(SWI)
+INT32
+_Semihost_SYS_OPEN(
+ IN UINTN SWI_0x01,
+ IN SEMIHOST_FILE_OPEN_BLOCK *OpenBlock
+ );
+
+__swi(SWI)
+INT32
+_Semihost_SYS_CLOSE(
+ IN UINTN SWI_0x02,
+ IN UINT32 *Handle
+ );
+
+__swi(SWI)
+VOID
+_Semihost_SYS_WRITEC(
+ IN UINTN SWI_0x03,
+ IN CHAR8 *Character
+ );
+
+__swi(SWI)
+VOID
+_Semihost_SYS_WRITE0(
+ IN UINTN SWI_0x04,
+ IN CHAR8 *String
+ );
+
+__swi(SWI)
+UINT32
+_Semihost_SYS_WRITE(
+ IN UINTN SWI_0x05,
+ IN OUT SEMIHOST_FILE_READ_WRITE_BLOCK *WriteBlock
+ );
+
+__swi(SWI)
+UINT32
+_Semihost_SYS_READ(
+ IN UINTN SWI_0x06,
+ IN OUT SEMIHOST_FILE_READ_WRITE_BLOCK *ReadBlock
+ );
+
+__swi(SWI)
+CHAR8
+_Semihost_SYS_READC(
+ IN UINTN SWI_0x07,
+ IN UINTN Zero
+ );
+
+__swi(SWI)
+INT32
+_Semihost_SYS_SEEK(
+ IN UINTN SWI_0x0A,
+ IN SEMIHOST_FILE_SEEK_BLOCK *SeekBlock
+ );
+
+__swi(SWI)
+INT32
+_Semihost_SYS_FLEN(
+ IN UINTN SWI_0x0C,
+ IN UINT32 *Handle
+ );
+
+__swi(SWI)
+UINT32
+_Semihost_SYS_TMPNAME(
+ IN UINTN SWI_0x0D,
+ IN SEMIHOST_FILE_TMPNAME_BLOCK *TmpNameBlock
+ );
+
+__swi(SWI)
+UINT32
+_Semihost_SYS_REMOVE(
+ IN UINTN SWI_0x0E,
+ IN SEMIHOST_FILE_REMOVE_BLOCK *RemoveBlock
+ );
+
+__swi(SWI)
+UINT32
+_Semihost_SYS_RENAME(
+ IN UINTN SWI_0x0F,
+ IN SEMIHOST_FILE_RENAME_BLOCK *RenameBlock
+ );
+
+__swi(SWI)
+UINT32
+_Semihost_SYS_SYSTEM(
+ IN UINTN SWI_0x12,
+ IN SEMIHOST_SYSTEM_BLOCK *SystemBlock
+ );
+
+#define Semihost_SYS_OPEN(OpenBlock) _Semihost_SYS_OPEN(0x01, OpenBlock)
+#define Semihost_SYS_CLOSE(Handle) _Semihost_SYS_CLOSE(0x02, Handle)
+#define Semihost_SYS_WRITE0(String) _Semihost_SYS_WRITE0(0x04, String)
+#define Semihost_SYS_WRITEC(Character) _Semihost_SYS_WRITEC(0x03, Character)
+#define Semihost_SYS_WRITE(WriteBlock) _Semihost_SYS_WRITE(0x05, WriteBlock)
+#define Semihost_SYS_READ(ReadBlock) _Semihost_SYS_READ(0x06, ReadBlock)
+#define Semihost_SYS_READC() _Semihost_SYS_READC(0x07, 0)
+#define Semihost_SYS_SEEK(SeekBlock) _Semihost_SYS_SEEK(0x0A, SeekBlock)
+#define Semihost_SYS_FLEN(Handle) _Semihost_SYS_FLEN(0x0C, Handle)
+#define Semihost_SYS_TMPNAME(TmpNameBlock) _Semihost_SYS_TMPNAME(0x0D, TmpNameBlock)
+#define Semihost_SYS_REMOVE(RemoveBlock) _Semihost_SYS_REMOVE(0x0E, RemoveBlock)
+#define Semihost_SYS_RENAME(RenameBlock) _Semihost_SYS_RENAME(0x0F, RenameBlock)
+#define Semihost_SYS_SYSTEM(SystemBlock) _Semihost_SYS_SYSTEM(0x12, SystemBlock)
+
+#elif defined(__GNUC__) // __CC_ARM
+
+#define SEMIHOST_SUPPORTED TRUE
+
+UINT32
+GccSemihostCall (
+ IN UINT32 Operation,
+ IN UINTN SystemBlockAddress
+ ); // __attribute__ ((interrupt ("SVC")));
+
+#define Semihost_SYS_OPEN(OpenBlock) GccSemihostCall(0x01, (UINTN)(OpenBlock))
+#define Semihost_SYS_CLOSE(Handle) GccSemihostCall(0x02, (UINTN)(Handle))
+#define Semihost_SYS_WRITE0(String) GccSemihostCall(0x04, (UINTN)(String))
+#define Semihost_SYS_WRITEC(Character) GccSemihostCall(0x03, (UINTN)(Character))
+#define Semihost_SYS_WRITE(WriteBlock) GccSemihostCall(0x05, (UINTN)(WriteBlock))
+#define Semihost_SYS_READ(ReadBlock) GccSemihostCall(0x06, (UINTN)(ReadBlock))
+#define Semihost_SYS_READC() GccSemihostCall(0x07, (UINTN)(0))
+#define Semihost_SYS_SEEK(SeekBlock) GccSemihostCall(0x0A, (UINTN)(SeekBlock))
+#define Semihost_SYS_FLEN(Handle) GccSemihostCall(0x0C, (UINTN)(Handle))
+#define Semihost_SYS_TMPNAME(TmpNameBlock) GccSemihostCall(0x0D, (UINTN)(TmpNameBlock))
+#define Semihost_SYS_REMOVE(RemoveBlock) GccSemihostCall(0x0E, (UINTN)(RemoveBlock))
+#define Semihost_SYS_RENAME(RenameBlock) GccSemihostCall(0x0F, (UINTN)(RenameBlock))
+#define Semihost_SYS_SYSTEM(SystemBlock) GccSemihostCall(0x12, (UINTN)(SystemBlock))
+
+#else // __CC_ARM
+
+#define SEMIHOST_SUPPORTED FALSE
+
+#define Semihost_SYS_OPEN(OpenBlock) (-1)
+#define Semihost_SYS_CLOSE(Handle) (-1)
+#define Semihost_SYS_WRITE0(String)
+#define Semihost_SYS_WRITEC(Character)
+#define Semihost_SYS_WRITE(WriteBlock) (0)
+#define Semihost_SYS_READ(ReadBlock) ((ReadBlock)->Length)
+#define Semihost_SYS_READC() ('x')
+#define Semihost_SYS_SEEK(SeekBlock) (-1)
+#define Semihost_SYS_FLEN(Handle) (-1)
+#define Semihost_SYS_TMPNAME(TmpNameBlock) (-1)
+#define Semihost_SYS_REMOVE(RemoveBlock) (-1)
+#define Semihost_SYS_RENAME(RenameBlock) (-1)
+#define Semihost_SYS_SYSTEM(SystemBlock) (-1)
+
+#endif // __CC_ARM
+
+#endif //__SEMIHOST_PRIVATE_H__
|