blob: 831774e35664aac289bf4f51cee5676438e47aa0 [file] [log] [blame]
Kautuk Consul1c03ab92022-12-07 17:12:34 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
4 * Copyright 2014 Broadcom Corporation
5 */
6
7#include <common.h>
8#include <log.h>
9#include <semihosting.h>
10
11#define SYSOPEN 0x01
12#define SYSCLOSE 0x02
13#define SYSWRITEC 0x03
14#define SYSWRITE0 0x04
15#define SYSWRITE 0x05
16#define SYSREAD 0x06
17#define SYSREADC 0x07
18#define SYSISERROR 0x08
19#define SYSSEEK 0x0A
20#define SYSFLEN 0x0C
21#define SYSERRNO 0x13
22
23#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
24static bool _semihosting_enabled = true;
25static bool try_semihosting = true;
26
27bool semihosting_enabled(void)
28{
29 if (try_semihosting) {
30 smh_trap(SYSERRNO, NULL);
31 try_semihosting = false;
32 }
33
34 return _semihosting_enabled;
35}
36
37void disable_semihosting(void)
38{
39 _semihosting_enabled = false;
40}
41#endif
42
43/**
44 * smh_errno() - Read the host's errno
45 *
46 * This gets the value of the host's errno and negates it. The host's errno may
47 * or may not be set, so only call this function if a previous semihosting call
48 * has failed.
49 *
50 * Return: a negative error value
51 */
52static int smh_errno(void)
53{
54 long ret = smh_trap(SYSERRNO, NULL);
55
56 if (ret > 0 && ret < INT_MAX)
57 return -ret;
58 return -EIO;
59}
60
61long smh_open(const char *fname, enum smh_open_mode mode)
62{
63 long fd;
64 struct smh_open_s {
65 const char *fname;
66 unsigned long mode;
67 size_t len;
68 } open;
69
70 debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode);
71
72 open.fname = fname;
73 open.len = strlen(fname);
74 open.mode = mode;
75
76 /* Open the file on the host */
77 fd = smh_trap(SYSOPEN, &open);
78 if (fd == -1)
79 return smh_errno();
80 return fd;
81}
82
83/**
84 * struct smg_rdwr_s - Arguments for read and write
85 * @fd: A file descriptor returned from smh_open()
86 * @memp: Pointer to a buffer of memory of at least @len bytes
87 * @len: The number of bytes to read or write
88 */
89struct smh_rdwr_s {
90 long fd;
91 void *memp;
92 size_t len;
93};
94
95long smh_read(long fd, void *memp, size_t len)
96{
97 long ret;
98 struct smh_rdwr_s read;
99
100 debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
101
102 read.fd = fd;
103 read.memp = memp;
104 read.len = len;
105
106 ret = smh_trap(SYSREAD, &read);
107 if (ret < 0)
108 return smh_errno();
109 return len - ret;
110}
111
112long smh_write(long fd, const void *memp, size_t len, ulong *written)
113{
114 long ret;
115 struct smh_rdwr_s write;
116
117 debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
118
119 write.fd = fd;
120 write.memp = (void *)memp;
121 write.len = len;
122
123 ret = smh_trap(SYSWRITE, &write);
124 *written = len - ret;
125 if (ret)
126 return smh_errno();
127 return 0;
128}
129
130long smh_close(long fd)
131{
132 long ret;
133
134 debug("%s: fd %ld\n", __func__, fd);
135
136 ret = smh_trap(SYSCLOSE, &fd);
137 if (ret == -1)
138 return smh_errno();
139 return 0;
140}
141
142long smh_flen(long fd)
143{
144 long ret;
145
146 debug("%s: fd %ld\n", __func__, fd);
147
148 ret = smh_trap(SYSFLEN, &fd);
149 if (ret == -1)
150 return smh_errno();
151 return ret;
152}
153
154long smh_seek(long fd, long pos)
155{
156 long ret;
157 struct smh_seek_s {
158 long fd;
159 long pos;
160 } seek;
161
162 debug("%s: fd %ld pos %ld\n", __func__, fd, pos);
163
164 seek.fd = fd;
165 seek.pos = pos;
166
167 ret = smh_trap(SYSSEEK, &seek);
168 if (ret)
169 return smh_errno();
170 return 0;
171}
172
173int smh_getc(void)
174{
175 return smh_trap(SYSREADC, NULL);
176}
177
178void smh_putc(char ch)
179{
180 smh_trap(SYSWRITEC, &ch);
181}
182
183void smh_puts(const char *s)
184{
185 smh_trap(SYSWRITE0, (char *)s);
186}