diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2007-07-12 12:12:34 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2007-07-12 12:12:34 +0200 |
commit | d757720766629dcd94af70ea65ccd8ba5eb47e4b (patch) | |
tree | 1263204fa6e46fc3555f232b81e6c9ce2bd13df2 /arch/sandbox/lib | |
parent | 2557787389f8ec40381d1201a15badd25d4aab10 (diff) | |
download | barebox-d757720766629dcd94af70ea65ccd8ba5eb47e4b.tar.gz barebox-d757720766629dcd94af70ea65ccd8ba5eb47e4b.tar.xz |
arch/linux -> arch/sandbox
Diffstat (limited to 'arch/sandbox/lib')
-rw-r--r-- | arch/sandbox/lib/Makefile | 12 | ||||
-rw-r--r-- | arch/sandbox/lib/common.c | 339 | ||||
-rw-r--r-- | arch/sandbox/lib/tap.c | 63 | ||||
-rw-r--r-- | arch/sandbox/lib/u-boot.lds.S | 229 |
4 files changed, 643 insertions, 0 deletions
diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile new file mode 100644 index 0000000000..418f4d3427 --- /dev/null +++ b/arch/sandbox/lib/Makefile @@ -0,0 +1,12 @@ +CPPFLAGS_u-boot.lds = -U$(SUBARCH) -DELF_ARCH=$(ELF_ARCH) \ + -DELF_FORMAT="$(ELF_FORMAT)" + +extra-y += u-boot.lds + +CPPFLAGS := -I/usr/include -Iinclude -P +CFLAGS := -Wall +#NOSTDINC_FLAGS := + +obj-y = common.o tap.o + +USER_OBJS := common.o diff --git a/arch/sandbox/lib/common.c b/arch/sandbox/lib/common.c new file mode 100644 index 0000000000..6416a54381 --- /dev/null +++ b/arch/sandbox/lib/common.c @@ -0,0 +1,339 @@ +/* + * common.c - common wrapper functions between U-Boot and the host + * + * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * These are host includes. Never include any U-Boot header + * files here... + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <termios.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <getopt.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <libgen.h> +#include <sys/mman.h> +#include <errno.h> +#include <signal.h> +#include <sys/select.h> +/* + * ...except the ones needed to connect with U-Boot + */ +#include <asm/arch/linux.h> +#include <asm/arch/hostfile.h> + +static struct termios term_orig, term_vi; +static char erase_char; /* the users erase character */ + +static void rawmode(void) +{ + tcgetattr(0, &term_orig); + term_vi = term_orig; + term_vi.c_lflag &= (~ICANON & ~ECHO & ~ISIG); + term_vi.c_iflag &= (~IXON & ~ICRNL); + term_vi.c_oflag |= (ONLCR); + term_vi.c_cc[VMIN] = 1; + term_vi.c_cc[VTIME] = 0; + erase_char = term_vi.c_cc[VERASE]; + tcsetattr(0, TCSANOW, &term_vi); +} + +static void cookmode(void) +{ + fflush(stdout); + tcsetattr(0, TCSANOW, &term_orig); +} + +void linux_putc(const char c) +{ + fputc(c, stdout); + + /* If \n, also do \r */ + if (c == '\n') + linux_putc ('\r'); + + fflush(stdout); +} + +int linux_tstc(int fd) +{ + fd_set rfds; + struct timeval tv; + int ret; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + /* + * We set the timeout here to 100us, because otherwise + * U-Boot would eat all cpu resources while waiting + * for input. On the other hand this makes some + * things like networking slow, because U-Boot will + * poll this function very often. + */ + tv.tv_sec = 0; + tv.tv_usec = 100; + + ret = select(fd + 1, &rfds, NULL, NULL, &tv); + + if (ret) + return 1; + + return 0; +} + +int linux_getc(void) +{ + char ret; + + read(0, &ret, 1); + + return ret; +} + +uint64_t linux_get_time(void) +{ + struct timespec ts; + uint64_t now; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + now = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec; + + return now; +} + +int reset_cpu(int unused) +{ + cookmode(); + exit(0); +} + +void enable_interrupts(void) +{ +} + +void disable_interrupt(void) +{ +} + +int linux_read(int fd, void *buf, size_t count) +{ + return read(fd, buf, count); +} + +int linux_read_nonblock(int fd, void *buf, size_t count) +{ + int oldflags, ret; + + oldflags = fcntl(fd, F_GETFL); + if (oldflags == -1) + goto err_out; + + if (fcntl(fd, F_SETFL, oldflags | O_NONBLOCK) == -1) + goto err_out; + + ret = read(fd, buf, count); + + if (fcntl(fd, F_SETFL, oldflags) == -1) + goto err_out; + + if (ret == -1) + usleep(100); + + return ret; + +err_out: + perror("fcntl"); + return -1; +} + +ssize_t linux_write(int fd, const void *buf, size_t count) +{ + return write(fd, buf, count); +} + +off_t linux_lseek(int fd, off_t offset) +{ + return lseek(fd, offset, SEEK_SET); +} + +void flush_cache(unsigned long dummy1, unsigned long dummy2) +{ + /* why should we? */ +} + +extern void start_uboot(void); +extern void mem_malloc_init(void *start, void *end); + +int add_image(char *str, char *name_template) +{ + char *file; + int readonly = 0, map = 1; + struct stat s; + char *opt; + int fd, ret; + struct hf_platform_data *hf = malloc(sizeof(struct hf_platform_data)); + + if (!hf) + return -1; + + file = strtok(str, ","); + while ((opt = strtok(NULL, ","))) { + if (!strcmp(opt, "ro")) + readonly = 1; + if (!strcmp(opt, "map")) + map = 1; + } + + printf("add file %s(%s)\n", file, readonly ? "ro" : ""); + + fd = open(file, readonly ? O_RDONLY : O_RDWR); + hf->fd = fd; + hf->filename = file; + + if (fd < 0) { + perror("open"); + goto err_out; + } + + if (fstat(fd, &s)) { + perror("fstat"); + goto err_out; + } + + hf->size = s.st_size; + + if (map) { + hf->map_base = (unsigned long)mmap(0, hf->size, + PROT_READ | (readonly ? 0 : PROT_WRITE), + MAP_SHARED, fd, 0); + if ((void *)hf->map_base == MAP_FAILED) + printf("warning: mmapping %s failed\n", file); + } + + + ret = u_boot_register_filedev(hf, name_template); + if (ret) + goto err_out; + return 0; + +err_out: + if (fd > 0) + close(fd); + free(hf); + return -1; +} + +static void print_usage(const char *prgname) +{ + printf( +"Usage: %s [OPTIONS]\n" +"Start U-Boot.\n" +"Options:\n" +" -i <file> Map a file to U-Boot. This option can be given multiple\n" +" times. The files will show up as /dev/fd0 ... /dev/fdx\n" +" under U-Boot.\n" +" -e <file> Map a file to U-Boot. With this option files are mapped as\n" +" /dev/env0 ... /dev/envx and thus are used as default\n" +" environment. An empty file generated with dd will do to get\n" +" started wth an empty environment\n" +" -O <file> Register file as a console capable of doing stdout. File can\n" +" be a regular file or a fifo.\n" +" -I <file> Register file as a console capable of doing stdin. File can\n" +" be a regular file or a fifo.\n", + prgname + ); +} + +int main(int argc, char *argv[]) +{ + void *ram; + int opt, ret, fd; + int malloc_size = 8 * 1024 * 1024; + + ram = malloc(malloc_size); + if (!ram) { + printf("unable to get malloc space\n"); + exit(1); + } + mem_malloc_init(ram, ram + malloc_size); + + while ((opt = getopt(argc, argv, "hi:e:I:O:")) != -1) { + switch (opt) { + case 'h': + print_usage(basename(argv[0])); + exit(0); + case 'i': + ret = add_image(optarg, "fd"); + if (ret) + exit(1); + break; + case 'm': + /* This option is broken. add_image needs malloc, so + * mem_alloc_init() has to be called before option + * parsing + */ + malloc_size = strtoul(optarg, NULL, 0); + break; + case 'e': + ret = add_image(optarg, "env"); + if (ret) + exit(1); + break; + case 'O': + fd = open(optarg, O_WRONLY); + if (fd < 0) { + perror("open"); + exit(1); + } + + u_boot_register_console("cout", -1, fd); + break; + case 'I': + fd = open(optarg, O_RDWR); + if (fd < 0) { + perror("open"); + exit(1); + } + + u_boot_register_console("cin", fd, -1); + break; + default: + exit(1); + } + } + + u_boot_register_console("console", 1, 0); + + rawmode(); + start_uboot(); + + /* never reached */ + return 0; +} + diff --git a/arch/sandbox/lib/tap.c b/arch/sandbox/lib/tap.c new file mode 100644 index 0000000000..b620612626 --- /dev/null +++ b/arch/sandbox/lib/tap.c @@ -0,0 +1,63 @@ +/* + * tap.c - host side functions for tap driver + * + * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <linux/if.h> +#include <linux/if_tun.h> +#include <string.h> + +int tap_alloc(char *dev) +{ + struct ifreq ifr; + int fd, err; + + if ((fd = open("/dev/net/tun", O_RDWR)) < 0) { + perror("could not open /dev/net/tun"); + return -1; + } + + memset(&ifr, 0, sizeof(ifr)); + + /* Flags: IFF_TUN - TUN device (no Ethernet headers) + * IFF_TAP - TAP device + * + * IFF_NO_PI - Do not provide packet information + */ + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + if (*dev) + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + + if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) { + perror("could not get tap device"); + close(fd); + return err; + } + + strcpy(dev, ifr.ifr_name); + return fd; +} diff --git a/arch/sandbox/lib/u-boot.lds.S b/arch/sandbox/lib/u-boot.lds.S new file mode 100644 index 0000000000..25d42b1e5e --- /dev/null +++ b/arch/sandbox/lib/u-boot.lds.S @@ -0,0 +1,229 @@ +#include <asm-generic/u-boot.lds.h> + +OUTPUT_FORMAT(ELF_FORMAT) +OUTPUT_ARCH(ELF_ARCH) +ENTRY(_start) + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = 0x400000); . = 0x400000 + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rel.ldata .rel.ldata.* .rel.gnu.linkonce.l.*) + *(.rel.lbss .rel.lbss.* .rel.gnu.linkonce.lb.*) + *(.rel.lrodata .rel.lrodata.* .rel.gnu.linkonce.lr.*) + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) + *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) + *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) + } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0x90909090 + .plt : { *(.plt) } + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + } =0x90909090 + + . = ALIGN(64); + __u_boot_initcalls_start = .; + __u_boot_initcalls : { INITCALLS } + __u_boot_initcalls_end = .; + . = ALIGN(64); + __u_boot_cmd_start = .; + __u_boot_cmd : { U_BOOT_CMDS } + __u_boot_cmd_end = .; + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) } + . = DATA_SEGMENT_RELRO_END (24, .); + .got.plt : { *(.got.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + .lbss : + { + *(.dynlbss) + *(.lbss .lbss.* .gnu.linkonce.lb.*) + *(LARGE_COMMON) + } + . = ALIGN(64 / 8); + .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : + { + *(.lrodata .lrodata.* .gnu.linkonce.lr.*) + } + .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : + { + *(.ldata .ldata.* .gnu.linkonce.l.*) + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + . = ALIGN(64 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} + |