2 * Copyright (c) 2011 The Chromium OS Authors.
3 * SPDX-License-Identifier: GPL-2.0+
20 #include <sys/types.h>
21 #include <linux/types.h>
23 #include <asm/getopt.h>
24 #include <asm/sections.h>
25 #include <asm/state.h>
28 /* Operating System Interface */
31 size_t length
; /* number of bytes in the block */
34 ssize_t
os_read(int fd
, void *buf
, size_t count
)
36 return read(fd
, buf
, count
);
39 ssize_t
os_read_no_block(int fd
, void *buf
, size_t count
)
41 const int flags
= fcntl(fd
, F_GETFL
, 0);
43 fcntl(fd
, F_SETFL
, flags
| O_NONBLOCK
);
44 return os_read(fd
, buf
, count
);
47 ssize_t
os_write(int fd
, const void *buf
, size_t count
)
49 return write(fd
, buf
, count
);
52 off_t
os_lseek(int fd
, off_t offset
, int whence
)
54 if (whence
== OS_SEEK_SET
)
56 else if (whence
== OS_SEEK_CUR
)
58 else if (whence
== OS_SEEK_END
)
62 return lseek(fd
, offset
, whence
);
65 int os_open(const char *pathname
, int os_flags
)
69 switch (os_flags
& OS_O_MASK
) {
84 if (os_flags
& OS_O_CREAT
)
87 return open(pathname
, flags
, 0777);
95 void os_exit(int exit_code
)
100 /* Restore tty state when we exit */
101 static struct termios orig_term
;
103 static void os_fd_restore(void)
105 tcsetattr(0, TCSANOW
, &orig_term
);
108 /* Put tty into raw mode so <tab> and <ctrl+c> work */
109 void os_tty_raw(int fd
)
111 static int setup
= 0;
118 /* If not a tty, don't complain */
119 if (tcgetattr(fd
, &orig_term
))
123 term
.c_iflag
= IGNBRK
| IGNPAR
;
124 term
.c_oflag
= OPOST
| ONLCR
;
125 term
.c_cflag
= CS8
| CREAD
| CLOCAL
;
127 if (tcsetattr(fd
, TCSANOW
, &term
))
130 atexit(os_fd_restore
);
133 void *os_malloc(size_t length
)
135 struct os_mem_hdr
*hdr
;
137 hdr
= mmap(NULL
, length
+ sizeof(*hdr
), PROT_READ
| PROT_WRITE
,
138 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
139 if (hdr
== MAP_FAILED
)
141 hdr
->length
= length
;
146 void *os_free(void *ptr
)
148 struct os_mem_hdr
*hdr
= ptr
;
152 munmap(hdr
, hdr
->length
+ sizeof(*hdr
));
155 void *os_realloc(void *ptr
, size_t length
)
157 struct os_mem_hdr
*hdr
= ptr
;
162 buf
= os_malloc(length
);
166 if (length
> hdr
->length
)
167 length
= hdr
->length
;
168 memcpy(buf
, ptr
, length
);
176 void os_usleep(unsigned long usec
)
181 uint64_t __attribute__((no_instrument_function
)) os_get_nsec(void)
183 #if defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK)
185 if (EINVAL
== clock_gettime(CLOCK_MONOTONIC
, &tp
)) {
188 gettimeofday(&tv
, NULL
);
189 tp
.tv_sec
= tv
.tv_sec
;
190 tp
.tv_nsec
= tv
.tv_usec
* 1000;
192 return tp
.tv_sec
* 1000000000ULL + tp
.tv_nsec
;
195 gettimeofday(&tv
, NULL
);
196 return tv
.tv_sec
* 1000000000ULL + tv
.tv_usec
* 1000;
200 static char *short_opts
;
201 static struct option
*long_opts
;
203 int os_parse_args(struct sandbox_state
*state
, int argc
, char *argv
[])
205 struct sandbox_cmdline_option
**sb_opt
= __u_boot_sandbox_option_start
;
206 size_t num_options
= __u_boot_sandbox_option_count();
209 int hidden_short_opt
;
214 if (short_opts
|| long_opts
)
220 /* dynamically construct the arguments to the system getopt_long */
221 short_opts
= os_malloc(sizeof(*short_opts
) * num_options
* 2 + 1);
222 long_opts
= os_malloc(sizeof(*long_opts
) * num_options
);
223 if (!short_opts
|| !long_opts
)
227 * getopt_long requires "val" to be unique (since that is what the
228 * func returns), so generate unique values automatically for flags
229 * that don't have a short option. pick 0x100 as that is above the
230 * single byte range (where ASCII/ISO-XXXX-X charsets live).
232 hidden_short_opt
= 0x100;
234 for (i
= 0; i
< num_options
; ++i
) {
235 long_opts
[i
].name
= sb_opt
[i
]->flag
;
236 long_opts
[i
].has_arg
= sb_opt
[i
]->has_arg
?
237 required_argument
: no_argument
;
238 long_opts
[i
].flag
= NULL
;
240 if (sb_opt
[i
]->flag_short
) {
241 short_opts
[si
++] = long_opts
[i
].val
= sb_opt
[i
]->flag_short
;
242 if (long_opts
[i
].has_arg
== required_argument
)
243 short_opts
[si
++] = ':';
245 long_opts
[i
].val
= sb_opt
[i
]->flag_short
= hidden_short_opt
++;
247 short_opts
[si
] = '\0';
249 /* we need to handle output ourselves since u-boot provides printf */
253 * walk all of the options the user gave us on the command line,
254 * figure out what u-boot option structure they belong to (via
255 * the unique short val key), and call the appropriate callback.
257 while ((c
= getopt_long(argc
, argv
, short_opts
, long_opts
, NULL
)) != -1) {
258 for (i
= 0; i
< num_options
; ++i
) {
259 if (sb_opt
[i
]->flag_short
== c
) {
260 if (sb_opt
[i
]->callback(state
, optarg
)) {
261 state
->parse_err
= sb_opt
[i
]->flag
;
267 if (i
== num_options
) {
269 * store the faulting flag for later display. we have to
270 * store the flag itself as the getopt parsing itself is
271 * tricky: need to handle the following flags (assume all
272 * of the below are unknown):
273 * -a optopt='a' optind=<next>
274 * -abbbb optopt='a' optind=<this>
275 * -aaaaa optopt='a' optind=<this>
276 * --a optopt=0 optind=<this>
277 * as you can see, it is impossible to determine the exact
278 * faulting flag without doing the parsing ourselves, so
279 * we just report the specific flag that failed.
282 static char parse_err
[3] = { '-', 0, '\0', };
283 parse_err
[1] = optopt
;
284 state
->parse_err
= parse_err
;
286 state
->parse_err
= argv
[optind
- 1];
294 void os_dirent_free(struct os_dirent_node
*node
)
296 struct os_dirent_node
*next
;
305 int os_dirent_ls(const char *dirname
, struct os_dirent_node
**headp
)
307 struct dirent entry
, *result
;
308 struct os_dirent_node
*head
, *node
, *next
;
316 dir
= opendir(dirname
);
320 /* Create a buffer for the maximum filename length */
321 len
= sizeof(entry
.d_name
) + strlen(dirname
) + 2;
328 for (node
= head
= NULL
;; node
= next
) {
329 ret
= readdir_r(dir
, &entry
, &result
);
332 next
= malloc(sizeof(*node
) + strlen(entry
.d_name
) + 1);
334 os_dirent_free(head
);
338 strcpy(next
->name
, entry
.d_name
);
339 switch (entry
.d_type
) {
341 next
->type
= OS_FILET_REG
;
344 next
->type
= OS_FILET_DIR
;
347 next
->type
= OS_FILET_LNK
;
351 snprintf(fname
, len
, "%s/%s", dirname
, next
->name
);
352 if (!stat(fname
, &buf
))
353 next
->size
= buf
.st_size
;
366 const char *os_dirent_typename
[OS_FILET_COUNT
] = {
373 const char *os_dirent_get_typename(enum os_dirent_t type
)
375 if (type
>= 0 && type
< OS_FILET_COUNT
)
376 return os_dirent_typename
[type
];
378 return os_dirent_typename
[OS_FILET_UNKNOWN
];
381 ssize_t
os_get_filesize(const char *fname
)
386 ret
= stat(fname
, &buf
);
397 void os_puts(const char *str
)
403 int os_write_ram_buf(const char *fname
)
405 struct sandbox_state
*state
= state_get_current();
408 fd
= open(fname
, O_CREAT
| O_WRONLY
, 0777);
411 ret
= write(fd
, state
->ram_buf
, state
->ram_size
);
413 if (ret
!= state
->ram_size
)
419 int os_read_ram_buf(const char *fname
)
421 struct sandbox_state
*state
= state_get_current();
425 size
= os_get_filesize(fname
);
428 if (size
!= state
->ram_size
)
430 fd
= open(fname
, O_RDONLY
);
434 ret
= read(fd
, state
->ram_buf
, state
->ram_size
);
436 if (ret
!= state
->ram_size
)