SemihostLib.c revision d276ac10f184aea06b5b484c8eeef88c5d6df881
1/** @file
2
3  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4  Copyright (c) 2013 - 2014, ARM Ltd. All rights reserved.<BR>
5
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
10
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.
13
14**/
15#include <Base.h>
16
17#include <Library/BaseLib.h>
18#include <Library/SemihostLib.h>
19
20#include "SemihostPrivate.h"
21
22BOOLEAN
23SemihostConnectionSupported (
24  VOID
25  )
26{
27  return SEMIHOST_SUPPORTED;
28}
29
30RETURN_STATUS
31SemihostFileOpen (
32  IN  CHAR8  *FileName,
33  IN  UINT32 Mode,
34  OUT UINTN  *FileHandle
35  )
36{
37  SEMIHOST_FILE_OPEN_BLOCK  OpenBlock;
38  INT32                     Result;
39
40  if (FileHandle == NULL) {
41    return RETURN_INVALID_PARAMETER;
42  }
43
44  // Remove any leading separator (e.g.: '\'). EFI Shell adds one.
45  if (*FileName == '\\') {
46    FileName++;
47  }
48
49  OpenBlock.FileName    = FileName;
50  OpenBlock.Mode        = Mode;
51  OpenBlock.NameLength  = AsciiStrLen(FileName);
52
53  Result = Semihost_SYS_OPEN(&OpenBlock);
54
55  if (Result == -1) {
56    return RETURN_NOT_FOUND;
57  } else {
58    *FileHandle = Result;
59    return RETURN_SUCCESS;
60  }
61}
62
63RETURN_STATUS
64SemihostFileSeek (
65  IN UINTN  FileHandle,
66  IN UINTN  Offset
67  )
68{
69  SEMIHOST_FILE_SEEK_BLOCK  SeekBlock;
70  INT32                     Result;
71
72  SeekBlock.Handle   = FileHandle;
73  SeekBlock.Location = Offset;
74
75  Result = Semihost_SYS_SEEK(&SeekBlock);
76
77  // Semihosting does not behave as documented. It returns the offset on
78  // success.
79  if (Result < 0) {
80    return RETURN_ABORTED;
81  } else {
82    return RETURN_SUCCESS;
83  }
84}
85
86RETURN_STATUS
87SemihostFileRead (
88  IN     UINTN  FileHandle,
89  IN OUT UINTN  *Length,
90  OUT    VOID   *Buffer
91  )
92{
93  SEMIHOST_FILE_READ_WRITE_BLOCK  ReadBlock;
94  UINT32                          Result;
95
96  if ((Length == NULL) || (Buffer == NULL)) {
97    return RETURN_INVALID_PARAMETER;
98  }
99
100  ReadBlock.Handle = FileHandle;
101  ReadBlock.Buffer = Buffer;
102  ReadBlock.Length = *Length;
103
104  Result = Semihost_SYS_READ(&ReadBlock);
105
106  if ((*Length != 0) && (Result == *Length)) {
107    return RETURN_ABORTED;
108  } else {
109    *Length -= Result;
110    return RETURN_SUCCESS;
111  }
112}
113
114RETURN_STATUS
115SemihostFileWrite (
116  IN     UINTN  FileHandle,
117  IN OUT UINTN  *Length,
118  IN     VOID   *Buffer
119  )
120{
121  SEMIHOST_FILE_READ_WRITE_BLOCK  WriteBlock;
122
123  if ((Length == NULL) || (Buffer == NULL)) {
124    return RETURN_INVALID_PARAMETER;
125  }
126
127  WriteBlock.Handle = FileHandle;
128  WriteBlock.Buffer = Buffer;
129  WriteBlock.Length = *Length;
130
131  *Length = Semihost_SYS_WRITE(&WriteBlock);
132
133  if (*Length != 0)
134    return RETURN_ABORTED;
135  else
136    return RETURN_SUCCESS;
137}
138
139RETURN_STATUS
140SemihostFileClose (
141  IN UINTN  FileHandle
142  )
143{
144  INT32 Result = Semihost_SYS_CLOSE(&FileHandle);
145
146  if (Result == -1) {
147    return RETURN_INVALID_PARAMETER;
148  } else {
149    return RETURN_SUCCESS;
150  }
151}
152
153RETURN_STATUS
154SemihostFileLength (
155  IN  UINTN  FileHandle,
156  OUT UINTN  *Length
157  )
158{
159  INT32       Result;
160
161  if (Length == NULL) {
162    return RETURN_INVALID_PARAMETER;
163  }
164
165  Result = Semihost_SYS_FLEN(&FileHandle);
166
167  if (Result == -1) {
168    return RETURN_ABORTED;
169  } else {
170    *Length = Result;
171    return RETURN_SUCCESS;
172  }
173}
174
175RETURN_STATUS
176SemihostFileRemove (
177  IN CHAR8 *FileName
178  )
179{
180  SEMIHOST_FILE_REMOVE_BLOCK  RemoveBlock;
181  UINT32                      Result;
182
183  // Remove any leading separator (e.g.: '\'). EFI Shell adds one.
184  if (*FileName == '\\') {
185    FileName++;
186  }
187
188  RemoveBlock.FileName    = FileName;
189  RemoveBlock.NameLength  = AsciiStrLen(FileName);
190
191  Result = Semihost_SYS_REMOVE(&RemoveBlock);
192
193  if (Result == 0) {
194    return RETURN_SUCCESS;
195  } else {
196    return RETURN_ABORTED;
197  }
198}
199
200CHAR8
201SemihostReadCharacter (
202  VOID
203  )
204{
205  return Semihost_SYS_READC();
206}
207
208VOID
209SemihostWriteCharacter (
210  IN CHAR8 Character
211  )
212{
213  Semihost_SYS_WRITEC(&Character);
214}
215
216VOID
217SemihostWriteString (
218  IN CHAR8 *String
219  )
220{
221  Semihost_SYS_WRITE0(String);
222}
223
224UINT32
225SemihostSystem (
226  IN CHAR8 *CommandLine
227  )
228{
229  SEMIHOST_SYSTEM_BLOCK SystemBlock;
230
231  SystemBlock.CommandLine   = CommandLine;
232  SystemBlock.CommandLength = AsciiStrLen(CommandLine);
233
234  return Semihost_SYS_SYSTEM(&SystemBlock);
235}
236