2012-05-02 21:46:40 +02:00
|
|
|
/** @file
|
|
|
|
|
|
|
|
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
2020-12-10 14:14:07 +01:00
|
|
|
Copyright (c) 2013 - 2021, Arm Limited. All rights reserved.<BR>
|
2014-03-25 12:04:41 +01:00
|
|
|
|
2019-04-04 01:03:18 +02:00
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
2012-05-02 21:46:40 +02:00
|
|
|
|
|
|
|
**/
|
|
|
|
#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,
|
2013-03-12 01:50:46 +01:00
|
|
|
OUT UINTN *FileHandle
|
2012-05-02 21:46:40 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
SEMIHOST_FILE_OPEN_BLOCK OpenBlock;
|
|
|
|
INT32 Result;
|
|
|
|
|
|
|
|
if (FileHandle == NULL) {
|
|
|
|
return RETURN_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2013-03-12 01:58:37 +01:00
|
|
|
// Remove any leading separator (e.g.: '\'). EFI Shell adds one.
|
|
|
|
if (*FileName == '\\') {
|
|
|
|
FileName++;
|
|
|
|
}
|
|
|
|
|
2012-05-02 21:46:40 +02:00
|
|
|
OpenBlock.FileName = FileName;
|
|
|
|
OpenBlock.Mode = Mode;
|
|
|
|
OpenBlock.NameLength = AsciiStrLen (FileName);
|
|
|
|
|
2021-01-08 16:12:06 +01:00
|
|
|
Result = SEMIHOST_SYS_OPEN (&OpenBlock);
|
2012-05-02 21:46:40 +02:00
|
|
|
|
|
|
|
if (Result == -1) {
|
|
|
|
return RETURN_NOT_FOUND;
|
|
|
|
} else {
|
|
|
|
*FileHandle = Result;
|
|
|
|
return RETURN_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_STATUS
|
|
|
|
SemihostFileSeek (
|
2013-03-12 01:50:46 +01:00
|
|
|
IN UINTN FileHandle,
|
|
|
|
IN UINTN Offset
|
2012-05-02 21:46:40 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
SEMIHOST_FILE_SEEK_BLOCK SeekBlock;
|
|
|
|
INT32 Result;
|
|
|
|
|
|
|
|
SeekBlock.Handle = FileHandle;
|
|
|
|
SeekBlock.Location = Offset;
|
|
|
|
|
2021-01-08 16:12:06 +01:00
|
|
|
Result = SEMIHOST_SYS_SEEK (&SeekBlock);
|
2012-05-02 21:46:40 +02:00
|
|
|
|
2014-03-25 12:04:41 +01:00
|
|
|
// Semihosting does not behave as documented. It returns the offset on
|
|
|
|
// success.
|
|
|
|
if (Result < 0) {
|
2012-05-02 21:46:40 +02:00
|
|
|
return RETURN_ABORTED;
|
2014-03-25 12:04:41 +01:00
|
|
|
} else {
|
|
|
|
return RETURN_SUCCESS;
|
2012-05-02 21:46:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_STATUS
|
|
|
|
SemihostFileRead (
|
2013-03-12 01:50:46 +01:00
|
|
|
IN UINTN FileHandle,
|
|
|
|
IN OUT UINTN *Length,
|
2012-05-02 21:46:40 +02:00
|
|
|
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;
|
|
|
|
|
2021-01-08 16:12:06 +01:00
|
|
|
Result = SEMIHOST_SYS_READ (&ReadBlock);
|
2012-05-02 21:46:40 +02:00
|
|
|
|
2014-03-25 12:04:41 +01:00
|
|
|
if ((*Length != 0) && (Result == *Length)) {
|
2012-05-02 21:46:40 +02:00
|
|
|
return RETURN_ABORTED;
|
|
|
|
} else {
|
|
|
|
*Length -= Result;
|
|
|
|
return RETURN_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_STATUS
|
|
|
|
SemihostFileWrite (
|
2013-03-12 01:50:46 +01:00
|
|
|
IN UINTN FileHandle,
|
|
|
|
IN OUT UINTN *Length,
|
2012-05-02 21:46:40 +02:00
|
|
|
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;
|
|
|
|
|
2021-01-08 16:12:06 +01:00
|
|
|
*Length = SEMIHOST_SYS_WRITE (&WriteBlock);
|
2014-03-25 12:04:41 +01:00
|
|
|
|
|
|
|
if (*Length != 0) {
|
|
|
|
return RETURN_ABORTED;
|
|
|
|
} else {
|
|
|
|
return RETURN_SUCCESS;
|
2021-12-05 23:53:50 +01:00
|
|
|
}
|
2012-05-02 21:46:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_STATUS
|
|
|
|
SemihostFileClose (
|
2013-03-12 01:50:46 +01:00
|
|
|
IN UINTN FileHandle
|
2012-05-02 21:46:40 +02:00
|
|
|
)
|
|
|
|
{
|
2021-01-08 16:12:06 +01:00
|
|
|
if (SEMIHOST_SYS_CLOSE (&FileHandle) == -1) {
|
2012-05-02 21:46:40 +02:00
|
|
|
return RETURN_INVALID_PARAMETER;
|
|
|
|
} else {
|
|
|
|
return RETURN_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_STATUS
|
|
|
|
SemihostFileLength (
|
2013-03-12 01:50:46 +01:00
|
|
|
IN UINTN FileHandle,
|
|
|
|
OUT UINTN *Length
|
2012-05-02 21:46:40 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
INT32 Result;
|
|
|
|
|
|
|
|
if (Length == NULL) {
|
|
|
|
return RETURN_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2021-01-08 16:12:06 +01:00
|
|
|
Result = SEMIHOST_SYS_FLEN (&FileHandle);
|
2012-05-02 21:46:40 +02:00
|
|
|
|
|
|
|
if (Result == -1) {
|
|
|
|
return RETURN_ABORTED;
|
|
|
|
} else {
|
|
|
|
*Length = Result;
|
|
|
|
return RETURN_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-27 11:38:18 +01:00
|
|
|
/**
|
|
|
|
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;
|
|
|
|
|
2021-01-08 16:12:06 +01:00
|
|
|
Result = SEMIHOST_SYS_TMPNAME (&TmpNameBlock);
|
2014-10-27 11:38:18 +01:00
|
|
|
|
|
|
|
if (Result != 0) {
|
|
|
|
return RETURN_ABORTED;
|
|
|
|
} else {
|
|
|
|
return RETURN_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-02 21:46:40 +02:00
|
|
|
RETURN_STATUS
|
|
|
|
SemihostFileRemove (
|
|
|
|
IN CHAR8 *FileName
|
|
|
|
)
|
|
|
|
{
|
|
|
|
SEMIHOST_FILE_REMOVE_BLOCK RemoveBlock;
|
|
|
|
UINT32 Result;
|
|
|
|
|
2014-03-25 12:04:41 +01:00
|
|
|
// Remove any leading separator (e.g.: '\'). EFI Shell adds one.
|
|
|
|
if (*FileName == '\\') {
|
|
|
|
FileName++;
|
|
|
|
}
|
|
|
|
|
2012-05-02 21:46:40 +02:00
|
|
|
RemoveBlock.FileName = FileName;
|
|
|
|
RemoveBlock.NameLength = AsciiStrLen (FileName);
|
|
|
|
|
2021-01-08 16:12:06 +01:00
|
|
|
Result = SEMIHOST_SYS_REMOVE (&RemoveBlock);
|
2012-05-02 21:46:40 +02:00
|
|
|
|
|
|
|
if (Result == 0) {
|
|
|
|
return RETURN_SUCCESS;
|
|
|
|
} else {
|
|
|
|
return RETURN_ABORTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-27 11:38:18 +01:00
|
|
|
/**
|
|
|
|
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);
|
|
|
|
|
2021-01-08 16:12:06 +01:00
|
|
|
Result = SEMIHOST_SYS_RENAME (&RenameBlock);
|
2014-10-27 11:38:18 +01:00
|
|
|
|
|
|
|
if (Result != 0) {
|
|
|
|
return RETURN_ABORTED;
|
|
|
|
} else {
|
|
|
|
return RETURN_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-02 21:46:40 +02:00
|
|
|
CHAR8
|
|
|
|
SemihostReadCharacter (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
2021-01-08 16:12:06 +01:00
|
|
|
return SEMIHOST_SYS_READC ();
|
2012-05-02 21:46:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
SemihostWriteCharacter (
|
|
|
|
IN CHAR8 Character
|
|
|
|
)
|
|
|
|
{
|
2021-01-08 16:12:06 +01:00
|
|
|
SEMIHOST_SYS_WRITEC (&Character);
|
2012-05-02 21:46:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
SemihostWriteString (
|
|
|
|
IN CHAR8 *String
|
|
|
|
)
|
|
|
|
{
|
2021-01-08 16:12:06 +01:00
|
|
|
SEMIHOST_SYS_WRITE0 (String);
|
2012-05-02 21:46:40 +02:00
|
|
|
}
|
2014-08-19 15:29:52 +02:00
|
|
|
|
2012-05-02 21:46:40 +02:00
|
|
|
UINT32
|
|
|
|
SemihostSystem (
|
|
|
|
IN CHAR8 *CommandLine
|
|
|
|
)
|
|
|
|
{
|
|
|
|
SEMIHOST_SYSTEM_BLOCK SystemBlock;
|
|
|
|
|
|
|
|
SystemBlock.CommandLine = CommandLine;
|
|
|
|
SystemBlock.CommandLength = AsciiStrLen (CommandLine);
|
|
|
|
|
2021-01-08 16:12:06 +01:00
|
|
|
return SEMIHOST_SYS_SYSTEM (&SystemBlock);
|
2012-05-02 21:46:40 +02:00
|
|
|
}
|