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 int os_unlink(const char *pathname
)
97 return unlink(pathname
);
100 void os_exit(int exit_code
)
105 /* Restore tty state when we exit */
106 static struct termios orig_term
;
107 static bool term_setup
;
109 static void os_fd_restore(void)
112 tcsetattr(0, TCSANOW
, &orig_term
);
115 /* Put tty into raw mode so <tab> and <ctrl+c> work */
116 void os_tty_raw(int fd
, bool allow_sigs
)
124 /* If not a tty, don't complain */
125 if (tcgetattr(fd
, &orig_term
))
129 term
.c_iflag
= IGNBRK
| IGNPAR
;
130 term
.c_oflag
= OPOST
| ONLCR
;
131 term
.c_cflag
= CS8
| CREAD
| CLOCAL
;
132 term
.c_lflag
= allow_sigs
? ISIG
: 0;
133 if (tcsetattr(fd
, TCSANOW
, &term
))
136 atexit(os_fd_restore
);
139 void *os_malloc(size_t length
)
141 struct os_mem_hdr
*hdr
;
143 hdr
= mmap(NULL
, length
+ sizeof(*hdr
), PROT_READ
| PROT_WRITE
,
144 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
145 if (hdr
== MAP_FAILED
)
147 hdr
->length
= length
;
152 void os_free(void *ptr
)
154 struct os_mem_hdr
*hdr
= ptr
;
158 munmap(hdr
, hdr
->length
+ sizeof(*hdr
));
161 void *os_realloc(void *ptr
, size_t length
)
163 struct os_mem_hdr
*hdr
= ptr
;
168 buf
= os_malloc(length
);
172 if (length
> hdr
->length
)
173 length
= hdr
->length
;
174 memcpy(buf
, ptr
, length
);
182 void os_usleep(unsigned long usec
)
187 uint64_t __attribute__((no_instrument_function
)) os_get_nsec(void)
189 #if defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK)
191 if (EINVAL
== clock_gettime(CLOCK_MONOTONIC
, &tp
)) {
194 gettimeofday(&tv
, NULL
);
195 tp
.tv_sec
= tv
.tv_sec
;
196 tp
.tv_nsec
= tv
.tv_usec
* 1000;
198 return tp
.tv_sec
* 1000000000ULL + tp
.tv_nsec
;
201 gettimeofday(&tv
, NULL
);
202 return tv
.tv_sec
* 1000000000ULL + tv
.tv_usec
* 1000;
206 static char *short_opts
;
207 static struct option
*long_opts
;
209 int os_parse_args(struct sandbox_state
*state
, int argc
, char *argv
[])
211 struct sandbox_cmdline_option
**sb_opt
= __u_boot_sandbox_option_start
;
212 size_t num_options
= __u_boot_sandbox_option_count();
215 int hidden_short_opt
;
220 if (short_opts
|| long_opts
)
226 /* dynamically construct the arguments to the system getopt_long */
227 short_opts
= os_malloc(sizeof(*short_opts
) * num_options
* 2 + 1);
228 long_opts
= os_malloc(sizeof(*long_opts
) * num_options
);
229 if (!short_opts
|| !long_opts
)
233 * getopt_long requires "val" to be unique (since that is what the
234 * func returns), so generate unique values automatically for flags
235 * that don't have a short option. pick 0x100 as that is above the
236 * single byte range (where ASCII/ISO-XXXX-X charsets live).
238 hidden_short_opt
= 0x100;
240 for (i
= 0; i
< num_options
; ++i
) {
241 long_opts
[i
].name
= sb_opt
[i
]->flag
;
242 long_opts
[i
].has_arg
= sb_opt
[i
]->has_arg
?
243 required_argument
: no_argument
;
244 long_opts
[i
].flag
= NULL
;
246 if (sb_opt
[i
]->flag_short
) {
247 short_opts
[si
++] = long_opts
[i
].val
= sb_opt
[i
]->flag_short
;
248 if (long_opts
[i
].has_arg
== required_argument
)
249 short_opts
[si
++] = ':';
251 long_opts
[i
].val
= sb_opt
[i
]->flag_short
= hidden_short_opt
++;
253 short_opts
[si
] = '\0';
255 /* we need to handle output ourselves since u-boot provides printf */
259 * walk all of the options the user gave us on the command line,
260 * figure out what u-boot option structure they belong to (via
261 * the unique short val key), and call the appropriate callback.
263 while ((c
= getopt_long(argc
, argv
, short_opts
, long_opts
, NULL
)) != -1) {
264 for (i
= 0; i
< num_options
; ++i
) {
265 if (sb_opt
[i
]->flag_short
== c
) {
266 if (sb_opt
[i
]->callback(state
, optarg
)) {
267 state
->parse_err
= sb_opt
[i
]->flag
;
273 if (i
== num_options
) {
275 * store the faulting flag for later display. we have to
276 * store the flag itself as the getopt parsing itself is
277 * tricky: need to handle the following flags (assume all
278 * of the below are unknown):
279 * -a optopt='a' optind=<next>
280 * -abbbb optopt='a' optind=<this>
281 * -aaaaa optopt='a' optind=<this>
282 * --a optopt=0 optind=<this>
283 * as you can see, it is impossible to determine the exact
284 * faulting flag without doing the parsing ourselves, so
285 * we just report the specific flag that failed.
288 static char parse_err
[3] = { '-', 0, '\0', };
289 parse_err
[1] = optopt
;
290 state
->parse_err
= parse_err
;
292 state
->parse_err
= argv
[optind
- 1];
300 void os_dirent_free(struct os_dirent_node
*node
)
302 struct os_dirent_node
*next
;
311 int os_dirent_ls(const char *dirname
, struct os_dirent_node
**headp
)
313 struct dirent entry
, *result
;
314 struct os_dirent_node
*head
, *node
, *next
;
322 dir
= opendir(dirname
);
326 /* Create a buffer for the maximum filename length */
327 len
= sizeof(entry
.d_name
) + strlen(dirname
) + 2;
334 for (node
= head
= NULL
;; node
= next
) {
335 ret
= readdir_r(dir
, &entry
, &result
);
338 next
= malloc(sizeof(*node
) + strlen(entry
.d_name
) + 1);
340 os_dirent_free(head
);
345 strcpy(next
->name
, entry
.d_name
);
346 switch (entry
.d_type
) {
348 next
->type
= OS_FILET_REG
;
351 next
->type
= OS_FILET_DIR
;
354 next
->type
= OS_FILET_LNK
;
358 snprintf(fname
, len
, "%s/%s", dirname
, next
->name
);
359 if (!stat(fname
, &buf
))
360 next
->size
= buf
.st_size
;
373 const char *os_dirent_typename
[OS_FILET_COUNT
] = {
380 const char *os_dirent_get_typename(enum os_dirent_t type
)
382 if (type
>= 0 && type
< OS_FILET_COUNT
)
383 return os_dirent_typename
[type
];
385 return os_dirent_typename
[OS_FILET_UNKNOWN
];
388 ssize_t
os_get_filesize(const char *fname
)
393 ret
= stat(fname
, &buf
);
404 void os_puts(const char *str
)
410 int os_write_ram_buf(const char *fname
)
412 struct sandbox_state
*state
= state_get_current();
415 fd
= open(fname
, O_CREAT
| O_WRONLY
, 0777);
418 ret
= write(fd
, state
->ram_buf
, state
->ram_size
);
420 if (ret
!= state
->ram_size
)
426 int os_read_ram_buf(const char *fname
)
428 struct sandbox_state
*state
= state_get_current();
432 size
= os_get_filesize(fname
);
435 if (size
!= state
->ram_size
)
437 fd
= open(fname
, O_RDONLY
);
441 ret
= read(fd
, state
->ram_buf
, state
->ram_size
);
443 if (ret
!= state
->ram_size
)
449 static int make_exec(char *fname
, const void *data
, int size
)
453 strcpy(fname
, "/tmp/u-boot.jump.XXXXXX");
457 if (write(fd
, data
, size
) < 0)
460 if (chmod(fname
, 0777))
466 static int add_args(char ***argvp
, const char *add_args
[], int count
)
471 for (argv
= *argvp
, argc
= 0; (*argvp
)[argc
]; argc
++)
474 argv
= malloc((argc
+ count
+ 1) * sizeof(char *));
476 printf("Out of memory for %d argv\n", count
);
479 memcpy(argv
, *argvp
, argc
* sizeof(char *));
480 memcpy(argv
+ argc
, add_args
, count
* sizeof(char *));
481 argv
[argc
+ count
] = NULL
;
487 int os_jump_to_image(const void *dest
, int size
)
489 struct sandbox_state
*state
= state_get_current();
490 char fname
[30], mem_fname
[30];
492 const char *extra_args
[5];
493 char **argv
= state
->argv
;
498 err
= make_exec(fname
, dest
, size
);
502 strcpy(mem_fname
, "/tmp/u-boot.mem.XXXXXX");
503 fd
= mkstemp(mem_fname
);
507 err
= os_write_ram_buf(mem_fname
);
513 extra_args
[0] = "-j";
514 extra_args
[1] = fname
;
515 extra_args
[2] = "-m";
516 extra_args
[3] = mem_fname
;
517 extra_args
[4] = "--rm_memory";
518 err
= add_args(&argv
, extra_args
,
519 sizeof(extra_args
) / sizeof(extra_args
[0]));
524 for (i
= 0; argv
[i
]; i
++)
525 printf("%d %s\n", i
, argv
[i
]);
531 err
= execv(fname
, argv
);
536 return unlink(fname
);