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 
22 BOOLEAN
SemihostConnectionSupported(VOID)23 SemihostConnectionSupported (
24   VOID
25   )
26 {
27   return SEMIHOST_SUPPORTED;
28 }
29 
30 RETURN_STATUS
SemihostFileOpen(IN CHAR8 * FileName,IN UINT32 Mode,OUT UINTN * FileHandle)31 SemihostFileOpen (
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 
63 RETURN_STATUS
SemihostFileSeek(IN UINTN FileHandle,IN UINTN Offset)64 SemihostFileSeek (
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 
86 RETURN_STATUS
SemihostFileRead(IN UINTN FileHandle,IN OUT UINTN * Length,OUT VOID * Buffer)87 SemihostFileRead (
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 
114 RETURN_STATUS
SemihostFileWrite(IN UINTN FileHandle,IN OUT UINTN * Length,IN VOID * Buffer)115 SemihostFileWrite (
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 
139 RETURN_STATUS
SemihostFileClose(IN UINTN FileHandle)140 SemihostFileClose (
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 
153 RETURN_STATUS
SemihostFileLength(IN UINTN FileHandle,OUT UINTN * Length)154 SemihostFileLength (
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 
175 /**
176   Get a temporary name for a file from the host running the debug agent.
177 
178   @param[out]  Buffer      Pointer to the buffer where the temporary name has to
179                            be stored
180   @param[in]   Identifier  File name identifier (integer in the range 0 to 255)
181   @param[in]   Length      Length of the buffer to store the temporary name
182 
183   @retval  RETURN_SUCCESS            Temporary name returned
184   @retval  RETURN_INVALID_PARAMETER  Invalid buffer address
185   @retval  RETURN_ABORTED            Temporary name not returned
186 
187 **/
188 RETURN_STATUS
SemihostFileTmpName(OUT VOID * Buffer,IN UINT8 Identifier,IN UINTN Length)189 SemihostFileTmpName(
190   OUT  VOID   *Buffer,
191   IN   UINT8  Identifier,
192   IN   UINTN  Length
193   )
194 {
195   SEMIHOST_FILE_TMPNAME_BLOCK  TmpNameBlock;
196   INT32                        Result;
197 
198   if (Buffer == NULL) {
199     return RETURN_INVALID_PARAMETER;
200   }
201 
202   TmpNameBlock.Buffer     = Buffer;
203   TmpNameBlock.Identifier = Identifier;
204   TmpNameBlock.Length     = Length;
205 
206   Result = Semihost_SYS_TMPNAME (&TmpNameBlock);
207 
208   if (Result != 0) {
209     return  RETURN_ABORTED;
210   } else {
211     return  RETURN_SUCCESS;
212   }
213 }
214 
215 RETURN_STATUS
SemihostFileRemove(IN CHAR8 * FileName)216 SemihostFileRemove (
217   IN CHAR8 *FileName
218   )
219 {
220   SEMIHOST_FILE_REMOVE_BLOCK  RemoveBlock;
221   UINT32                      Result;
222 
223   // Remove any leading separator (e.g.: '\'). EFI Shell adds one.
224   if (*FileName == '\\') {
225     FileName++;
226   }
227 
228   RemoveBlock.FileName    = FileName;
229   RemoveBlock.NameLength  = AsciiStrLen(FileName);
230 
231   Result = Semihost_SYS_REMOVE(&RemoveBlock);
232 
233   if (Result == 0) {
234     return RETURN_SUCCESS;
235   } else {
236     return RETURN_ABORTED;
237   }
238 }
239 
240 /**
241   Rename a specified file.
242 
243   @param[in]  FileName     Name of the file to rename.
244   @param[in]  NewFileName  The new name of the file.
245 
246   @retval  RETURN_SUCCESS            File Renamed
247   @retval  RETURN_INVALID_PARAMETER  Either the current or the new name is not specified
248   @retval  RETURN_ABORTED            Rename failed
249 
250 **/
251 RETURN_STATUS
SemihostFileRename(IN CHAR8 * FileName,IN CHAR8 * NewFileName)252 SemihostFileRename(
253   IN  CHAR8  *FileName,
254   IN  CHAR8  *NewFileName
255   )
256 {
257   SEMIHOST_FILE_RENAME_BLOCK  RenameBlock;
258   INT32                       Result;
259 
260   if ((FileName == NULL) || (NewFileName == NULL)) {
261     return RETURN_INVALID_PARAMETER;
262   }
263 
264   RenameBlock.FileName          = FileName;
265   RenameBlock.FileNameLength    = AsciiStrLen (FileName);
266   RenameBlock.NewFileName       = NewFileName;
267   RenameBlock.NewFileNameLength = AsciiStrLen (NewFileName);
268 
269   Result = Semihost_SYS_RENAME (&RenameBlock);
270 
271   if (Result != 0) {
272     return  RETURN_ABORTED;
273   } else {
274     return  RETURN_SUCCESS;
275   }
276 }
277 
278 CHAR8
SemihostReadCharacter(VOID)279 SemihostReadCharacter (
280   VOID
281   )
282 {
283   return Semihost_SYS_READC();
284 }
285 
286 VOID
SemihostWriteCharacter(IN CHAR8 Character)287 SemihostWriteCharacter (
288   IN CHAR8 Character
289   )
290 {
291   Semihost_SYS_WRITEC(&Character);
292 }
293 
294 VOID
SemihostWriteString(IN CHAR8 * String)295 SemihostWriteString (
296   IN CHAR8 *String
297   )
298 {
299   Semihost_SYS_WRITE0(String);
300 }
301 
302 UINT32
SemihostSystem(IN CHAR8 * CommandLine)303 SemihostSystem (
304   IN CHAR8 *CommandLine
305   )
306 {
307   SEMIHOST_SYSTEM_BLOCK SystemBlock;
308 
309   SystemBlock.CommandLine   = CommandLine;
310   SystemBlock.CommandLength = AsciiStrLen(CommandLine);
311 
312   return Semihost_SYS_SYSTEM(&SystemBlock);
313 }
314