Cristian Măgherușan-Stanciu (cristi.magherusan@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1089
-gerrit
commit 1fe88701e5b66c6f1d8d1fcf18731746981b794c Author: Rudolf Marek r.marek@assembler.cz Date: Tue Jun 5 00:15:56 2012 +0200
userspace coreboot support
Add the basic linux userspace support. Avoid the priviledge ops and map low mem area to 64KB (which is normally mappable) Provide the linux sycall & console.
Change-Id: Iaeef5c159a1e8871ea24f57b4fd161f979a4ed77 Signed-off-by: Rudolf Marek r.marek@assembler.cz --- src/Kconfig | 20 ++++ src/arch/x86/boot/gdt.c | 5 +- src/arch/x86/boot/tables.c | 6 ++ src/arch/x86/include/arch/io.h | 76 ++++++++++++++ src/arch/x86/lib/c_start.S | 36 ++++++- src/arch/x86/lib/ebda.c | 3 + src/boot/hardwaremain.c | 12 ++- src/console/Makefile.inc | 1 + src/console/ulinux_console.c | 18 ++++ src/include/cpu/x86/lapic.h | 12 +++ src/include/termios.h | 219 +++++++++++++++++++++++++++++++++++++++++ src/include/ulinux.h | 36 +++++++ src/lib/Makefile.inc | 3 + src/lib/ulinux.c | 160 ++++++++++++++++++++++++++++++ 14 files changed, 602 insertions(+), 5 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig index 9630e0c..dce26b3 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -194,6 +194,26 @@ config REQUIRES_BLOB coreboot build for such a board can override this manually, but this option serves as warning that it might fail.
+config ULINUX + bool "Compile and run coreboot as Linux userspace process" + default n + help + This option enables to run coreboot as Linux process which + communicates with hardware using SerialICE. + +config ULINUX_VALGRIND + bool "Add valgrind instrumentation" + default n + depends on ULINUX + help + This option enables to track heap using valgrind. + +config SERIALICE_HOST_DEV + string "SerialICE host device" + default "/dev/ttyUSB0" + depends on ULINUX + help + Selects the serial port to which is connected your remote target. endmenu
source src/mainboard/Kconfig diff --git a/src/arch/x86/boot/gdt.c b/src/arch/x86/boot/gdt.c index b425ade..407cfe2 100644 --- a/src/arch/x86/boot/gdt.c +++ b/src/arch/x86/boot/gdt.c @@ -38,7 +38,9 @@ void move_gdt(void) { void *newgdt; u16 num_gdt_bytes = &gdt_end - &gdt; +#if CONFIG_ULINUX == 0 struct gdtarg gdtarg; +#endif
newgdt = cbmem_find(CBMEM_ID_GDT); if (!newgdt) { @@ -50,11 +52,12 @@ void move_gdt(void) printk(BIOS_DEBUG, "Moving GDT to %p...", newgdt); memcpy((void*)newgdt, &gdt, num_gdt_bytes); } - +#if CONFIG_ULINUX == 0 gdtarg.base = (u32)newgdt; gdtarg.limit = num_gdt_bytes - 1;
__asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg)); +#endif printk(BIOS_DEBUG, "ok\n"); }
diff --git a/src/arch/x86/boot/tables.c b/src/arch/x86/boot/tables.c index df4729a..44c03c5 100644 --- a/src/arch/x86/boot/tables.c +++ b/src/arch/x86/boot/tables.c @@ -32,6 +32,7 @@ #include <cbmem.h> #include <lib.h> #include <smbios.h> +#include <ulinux.h>
uint64_t high_tables_base = 0; uint64_t high_tables_size; @@ -69,7 +70,12 @@ struct lb_memory *write_tables(void) * and the coreboot table use low_tables. */ low_table_start = 0; +#if CONFIG_ULINUX + low_table_end = 0x10000; + ulinux_mmap(low_table_end, 0x1000); +#else low_table_end = 0x500; +#endif
#if CONFIG_GENERATE_PIRQ_TABLE #define MAX_PIRQ_TABLE_SIZE (4 * 1024) diff --git a/src/arch/x86/include/arch/io.h b/src/arch/x86/include/arch/io.h index f4c6967..88338e1 100644 --- a/src/arch/x86/include/arch/io.h +++ b/src/arch/x86/include/arch/io.h @@ -9,6 +9,7 @@ * (insb/insw/insl/outsb/outsw/outsl). */ #if defined(__ROMCC__) + static inline void outb(uint8_t value, uint16_t port) { __builtin_outb(value, port); @@ -41,6 +42,9 @@ static inline uint32_t inl(uint16_t port) return __builtin_inl(port); } #else + +#if defined(__PRE_RAM__) || defined(__SMM__) || CONFIG_ULINUX == 0 + static inline void outb(uint8_t value, uint16_t port) { __asm__ __volatile__ ("outb %b0, %w1" : : "a" (value), "Nd" (port)); @@ -76,6 +80,43 @@ static inline uint32_t inl(uint16_t port) __asm__ __volatile__ ("inl %w1, %0" : "=a"(value) : "Nd" (port)); return value; } + +#else /* CONFIG_ULINUX == 1 */ + +#include <console/console.h> +#include <serialice_host.h> + +static inline void outb(uint8_t value, uint16_t port) +{ + serialice_outb(value, port); +} + +static inline void outw(uint16_t value, uint16_t port) +{ + serialice_outw(value, port); +} + +static inline void outl(uint32_t value, uint16_t port) +{ + serialice_outl(value, port); +} + +static inline uint8_t inb(uint16_t port) +{ + return serialice_inb(port); +} + +static inline uint16_t inw(uint16_t port) +{ + return serialice_inw(port); +} + +static inline uint32_t inl(uint16_t port) +{ + return serialice_inl(port); +} + +#endif /* CONFIG_ULINUX */ #endif /* __ROMCC__ */
static inline void outsb(uint16_t port, const void *addr, unsigned long count) @@ -133,6 +174,9 @@ static inline void insl(uint16_t port, void *addr, unsigned long count) ); }
+ +#if defined(__PRE_RAM__) || defined(__SMM__) || CONFIG_ULINUX == 0 + static inline __attribute__((always_inline)) uint8_t read8(unsigned long addr) { return *((volatile uint8_t *)(addr)); @@ -163,5 +207,37 @@ static inline __attribute__((always_inline)) void write32(unsigned long addr, ui *((volatile uint32_t *)(addr)) = value; }
+#else /* CONFIG_ULINUX */ + +static inline __attribute__((always_inline)) uint8_t read8(unsigned long addr) +{ + return serialice_readb(addr); +} + +static inline __attribute__((always_inline)) uint16_t read16(unsigned long addr) +{ + return serialice_readw(addr); +} + +static inline __attribute__((always_inline)) uint32_t read32(unsigned long addr) +{ + return serialice_readl(addr); +} + +static inline __attribute__((always_inline)) void write8(unsigned long addr, uint8_t value) +{ + serialice_writeb(value, addr); +} + +static inline __attribute__((always_inline)) void write16(unsigned long addr, uint16_t value) +{ + serialice_writew(value, addr); +} + +static inline __attribute__((always_inline)) void write32(unsigned long addr, uint32_t value) +{ + serialice_writel(value, addr); +} +#endif #endif
diff --git a/src/arch/x86/lib/c_start.S b/src/arch/x86/lib/c_start.S index 9c1fdb1..ca37a19 100644 --- a/src/arch/x86/lib/c_start.S +++ b/src/arch/x86/lib/c_start.S @@ -4,6 +4,8 @@ .code32 .globl _start _start: + +#if CONFIG_ULINUX == 0 cli lgdt %cs:gdtaddr ljmp $0x10, $1f @@ -13,8 +15,8 @@ _start: movl %eax, %ss movl %eax, %fs movl %eax, %gs - post_code(POST_ENTRY_C_START) /* post 13 */ +#endif
/** poison the stack. Code should not count on the * stack being full of zeros. This stack poisoning @@ -53,7 +55,7 @@ _start:
/* Save the stack location */ movl %esp, %ebp - +#if CONFIG_ULINUX == 0 /* Initialize the Interrupt Descriptor table */ leal _idt, %edi leal vec0, %ebx @@ -71,13 +73,13 @@ _start:
/* Load the Interrupt descriptor table */ lidt idtarg - /* * Now we are finished. Memory is up, data is copied and * bss is cleared. Now we call the main routine and * let it do the rest. */ post_code(POST_PRE_HARDWAREMAIN) /* post fe */ +#endif
/* Restore the stack location */ movl %ebp, %esp @@ -322,3 +324,31 @@ _idt_end:
.previous .code32 + +#if CONFIG_ULINUX + .globl _call_linux + /* be paranoid of what registers to preserve for GCC */ +_call_linux: + pushl %ebp + movl %esp, %ebp + push %ebx + push %ecx + push %edx + push %esi + push %edi + movl 0x8(%ebp), %eax + movl 0xc(%ebp), %ebx + movl 0x10(%ebp), %ecx + movl 0x14(%ebp), %edx + movl 0x18(%ebp), %esi + movl 0x1c(%ebp), %edi + movl 0x20(%ebp), %ebp + int $0x80 + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret +#endif diff --git a/src/arch/x86/lib/ebda.c b/src/arch/x86/lib/ebda.c index fb407b6..1a1d16d 100644 --- a/src/arch/x86/lib/ebda.c +++ b/src/arch/x86/lib/ebda.c @@ -35,6 +35,9 @@ void setup_ebda(u32 low_memory_size, u16 ebda_segment, u16 ebda_size) return; #endif
+#if CONFIG_ULINUX + return; +#endif if (!low_memory_size || !ebda_segment || !ebda_size) return;
diff --git a/src/boot/hardwaremain.c b/src/boot/hardwaremain.c index 099ab3a..470b20e 100644 --- a/src/boot/hardwaremain.c +++ b/src/boot/hardwaremain.c @@ -36,6 +36,9 @@ it with the version available from LANL. #include <boot/elf.h> #include <cbfs.h> #include <lib.h> +#if CONFIG_ULINUX +#include <ulinux.h> +#endif #if CONFIG_HAVE_ACPI_RESUME #include <arch/acpi.h> #endif @@ -64,6 +67,10 @@ void hardwaremain(int boot_complete) #endif post_code(POST_ENTRY_RAMSTAGE);
+#if CONFIG_ULINUX + ulinux_init(); +#endif + /* console_init() MUST PRECEDE ALL printk()! */ console_init();
@@ -146,7 +153,10 @@ void hardwaremain(int boot_complete) lb_mem = write_tables();
timestamp_add_now(TS_LOAD_PAYLOAD); - +#if CONFIG_ULINUX + printk(BIOS_INFO, "All done, exiting\n"); + ulinux_exit(0); +#endif void *payload; payload = cbfs_load_payload(lb_mem, CONFIG_CBFS_PREFIX "/payload"); if (! payload) diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index f8928ad..c1d55da 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -20,6 +20,7 @@ driver-$(CONFIG_USBDEBUG) += usbdebug_console.c driver-$(CONFIG_CONSOLE_LOGBUF) += logbuf_console.c driver-$(CONFIG_CONSOLE_NE2K) += ne2k_console.c driver-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c +driver-$(CONFIG_ULINUX) += ulinux_console.c
$(obj)/console/console.ramstage.o : $(obj)/build.h diff --git a/src/console/ulinux_console.c b/src/console/ulinux_console.c new file mode 100644 index 0000000..4a5dd47 --- /dev/null +++ b/src/console/ulinux_console.c @@ -0,0 +1,18 @@ +#include <console/console.h> +#include <ulinux.h> + +static void linux_tx_byte(unsigned char byte) +{ + unsigned char c; + c = byte; + + ulinux_write(1, &c, 1); +} + + +static const struct console_driver linux_console __console = { + .init = 0, + .tx_byte = linux_tx_byte, + .rx_byte = 0, + .tst_byte = 0, +}; diff --git a/src/include/cpu/x86/lapic.h b/src/include/cpu/x86/lapic.h index 078f2a7..a6a07c1 100644 --- a/src/include/cpu/x86/lapic.h +++ b/src/include/cpu/x86/lapic.h @@ -5,6 +5,10 @@ #include <cpu/x86/msr.h> #include <arch/hlt.h>
+#if CONFIG_ULINUX && !defined(__PRE_RAM__) +#include <serialice_host.h> +#endif + /* See if I need to initialize the local apic */ #if CONFIG_SMP || CONFIG_IOAPIC # define NEED_LAPIC 1 @@ -14,12 +18,20 @@
static inline __attribute__((always_inline)) unsigned long lapic_read(unsigned long reg) { +#if CONFIG_ULINUX && !defined(__PRE_RAM__) + return serialice_readl((LAPIC_DEFAULT_BASE+reg)); +#else return *((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg)); +#endif }
static inline __attribute__((always_inline)) void lapic_write(unsigned long reg, unsigned long v) { +#if CONFIG_ULINUX && !defined(__PRE_RAM__) + serialice_writel(v, LAPIC_DEFAULT_BASE+reg); +#else *((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg)) = v; +#endif }
static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void) diff --git a/src/include/termios.h b/src/include/termios.h new file mode 100644 index 0000000..5133e6b --- /dev/null +++ b/src/include/termios.h @@ -0,0 +1,219 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +///# error "Never include <bits/termios.h> directly; use <termios.h> instead." +#define _TERMIOS_H + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 + }; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0000400 +# define NL0 0000000 +# define NL1 0000400 +# define CRDLY 0003000 +# define CR0 0000000 +# define CR1 0001000 +# define CR2 0002000 +# define CR3 0003000 +# define TABDLY 0014000 +# define TAB0 0000000 +# define TAB1 0004000 +# define TAB2 0010000 +# define TAB3 0014000 +# define BSDLY 0020000 +# define BS0 0000000 +# define BS1 0020000 +# define FFDLY 0100000 +# define FF0 0000000 +# define FF1 0100000 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#define __MAX_BAUD B4000000 +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#ifdef __USE_MISC +# define ECHOCTL 0001000 +# define ECHOPRT 0002000 +# define ECHOKE 0004000 +# define FLUSHO 0010000 +# define PENDIN 0040000 +#endif +#define IEXTEN 0100000 + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) +#endif diff --git a/src/include/ulinux.h b/src/include/ulinux.h new file mode 100644 index 0000000..e0408ad --- /dev/null +++ b/src/include/ulinux.h @@ -0,0 +1,36 @@ +#include <stdint.h> +#include <termios.h> +extern int _call_linux(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6); + +void __stack_chk_init(void); +void *ulinux_mmap(unsigned long addr, unsigned int length); +int ulinux_write(int fd, const void *buf, unsigned int count); +int ulinux_close(int fd); +int ulinux_read(int fd, void *buf, unsigned int count); +int ulinux_open(const char *pathname, int flags); + +#define EINTR 4 +extern int ulinux_errno; + +#define O_RDWR 00000002 +#define O_NOCTTY 0400 /* not fcntl */ +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define F_SETFL 4 /* Set file status flags. */ +#define EOF -1 + +#define perror(x) printk(BIOS_ERR, x) + +int ulinux_ioctl(int d, int request); + +int ulinux_tcgetattr(int fd, struct termios *termios_p); +int ulinux_cfsetispeed(struct termios *termios_p, speed_t speed); +int ulinux_cfsetospeed(struct termios *termios_p, speed_t speed); +int ulinux_tcsetattr(int fd, int optional_actions, + const struct termios *termios_p); +void ulinux_exit(int status); +int ulinux_fcntl(int fd, int cmd, int a); +int ulinux_tcflush(int fd, int queue_selector); +void ulinux_init(void); + +#define TIOCEXCL 0x540C diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index ec57bc2..6eeae78 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -44,6 +44,9 @@ ramstage-y += stack.c ramstage-y += gcc.c ramstage-y += clog2.c ramstage-y += cbmem.c +ramstage-$(CONFIG_ULINUX) += ulinux.c +ramstage-$(CONFIG_ULINUX) += serialice_host.c + ramstage-$(CONFIG_CONSOLE_SERIAL8250) += uart8250.c ramstage-$(CONFIG_CONSOLE_SERIAL8250MEM) += uart8250mem.c ramstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c diff --git a/src/lib/ulinux.c b/src/lib/ulinux.c new file mode 100644 index 0000000..a9c0431 --- /dev/null +++ b/src/lib/ulinux.c @@ -0,0 +1,160 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Rudolf Marek r.marek@assembler.cz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdlib.h> +#include <console/console.h> +#include <serialice_host.h> +#include <ulinux.h> + +#if CONFIG_ULINUX_VALGRIND +#include "valgrind.h" +#include "memcheck.h" +extern unsigned char _heap, _eheap; +#endif + +#define NR_EXIT 1 +#define NR_MMAP 192 +#define NR_READ 3 +#define NR_WRITE 4 +#define NR_OPEN 5 +#define NR_CLOSE 6 +#define NR_IOCTL 54 +#define NR_FCNTL 55 + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCFLSH 0x540b + +int ulinux_errno; + + +unsigned long __stack_chk_guard = 0xdeadbeef; + +void __stack_chk_init(void) +{ +} + +void __stack_chk_fail(void); + +void __attribute__ ((noreturn)) __stack_chk_fail(void) +{ + die("Stack SMASHED\n"); +} + +void ulinux_init(void) +{ + /* Map last 64KB of 1MB */ + ulinux_mmap((960 * 1024), 64 * 1024); + +#if CONFIG_ULINUX_VALGRIND + VALGRIND_CREATE_MEMPOOL(&_heap, 8, 0); + VALGRIND_MAKE_MEM_NOACCESS(&_heap, &_eheap - &_heap); +#endif + +// serialice_init(); + +} + +void *ulinux_mmap(unsigned long addr, unsigned int size) +{ + return (void *) _call_linux(NR_MMAP, (uint32_t) addr, size, + (uint32_t) 3, 0x32, -1, 0); +} + +int ulinux_write(int fd, const void *buf, unsigned int count) +{ + return _call_linux(NR_WRITE, (uint32_t) fd, (uint32_t) buf, + (uint32_t) count, 0, 0, 0); +} + +int ulinux_close(int fd) +{ + return _call_linux(NR_CLOSE, (uint32_t) fd, 0, 0, 0, 0, 0); +} + +int ulinux_read(int fd, void *buf, unsigned int count) +{ + int ret = + _call_linux(NR_READ, (uint32_t) fd, (uint32_t) buf, + (uint32_t) count, + 0, 0, 0); + ulinux_errno = (ret < 0) ? -ret : 0; + return ret; +} + + +int ulinux_open(const char *pathname, int flags) +{ + return _call_linux(NR_OPEN, (uint32_t) pathname, (uint32_t) flags, + (uint32_t) 0, 0, 0, 0); + +} + + +int ulinux_ioctl(int fd, int request) +{ + return _call_linux(NR_IOCTL, (uint32_t) fd, (uint32_t) request, + (uint32_t) 0, 0, 0, 0); +} + +int ulinux_tcgetattr(int fd, struct termios *termios_p) +{ + return _call_linux(NR_IOCTL, (uint32_t) fd, TCGETS, + (uint32_t) termios_p, 0, 0, 0); +} + + +int ulinux_cfsetispeed(struct termios *termios_p, speed_t speed) +{ + termios_p->c_ispeed = speed; + return 0; +} + +int ulinux_cfsetospeed(struct termios *termios_p, speed_t speed) +{ + termios_p->c_ospeed = speed; + return 0; +} + +int ulinux_tcsetattr(int fd, int optional_actions, + const struct termios *termios_p) +{ + return _call_linux(NR_IOCTL, (uint32_t) fd, TCSETS, + (uint32_t) termios_p, + (uint32_t) optional_actions, 0, 0); + +} + +void ulinux_exit(int status) +{ + _call_linux(NR_EXIT, status, 0, 0, 0, 0, 0); +} + +int ulinux_fcntl(int fd, int cmd, int a) +{ + return _call_linux(NR_FCNTL, (uint32_t) fd, (uint32_t) cmd, + (uint32_t) a, 0, 0, 0); +} + +int ulinux_tcflush(int fd, int queue_selector) +{ + return _call_linux(NR_IOCTL, (uint32_t) fd, TCFLSH, + (uint32_t) queue_selector, 0, 0, 0); + +}