/** @file Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
Copyright (c) 2013 - 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #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 ) { if (SEMIHOST_SYS_CLOSE (&FileHandle) == -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); }