commit 4c21257b1984c358159853bf4ae683cae0b96404
Author: Dimitris Papastamos <dimitris.papastamos@arm.com>
Date: Wed, 10 Oct 2018 14:10:04 +0100
Initial commit
Diffstat:
213 files changed, 5363 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,23 @@
+PROJECTDIR = .
+include scripts/rules.mk
+
+all: arch/$(ARCH)
+
+test: all FORCE
+ @+cd test/ && $(MAKE) test
+
+arch/$(ARCH): src
+
+src: lib bin
+
+bin lib:
+ mkdir $@
+
+src arch/$(ARCH): FORCE
+ +@cd $@ && $(MAKE)
+
+clean:
+ +@cd src && $(MAKE) clean
+ +@cd arch && $(MAKE) clean
+ +@cd test && $(MAKE) clean
+ rm -rf lib bin
diff --git a/README b/README
@@ -0,0 +1,33 @@
+Building rcode
+==============
+
+PATH=<path-to-aarch64-elf-toolchain>:$PATH
+export PATH
+make
+
+Running rcode
+=============
+
+You need the ATG Bowmore model. Launch the model with the following
+options:
+
+#!/bin/sh
+
+bl1_path=<path-to-bl1.bin>
+fip_path=<path-to-fip.bin>
+romfw_path=<path-to-rcode-romfw.bin>
+
+isim_system \
+ -p -S -R \
+ -C bp.pl011_uart0.uart_enable=1 \
+ -C bp.pl011_uart0.out_file=uart0.out \
+ -C cluster0.NUM_CORES=1 \
+ -C cluster0.has_bowmore=1 \
+ -C cluster0.cpu0.RVBAR_R=0x2e000000 \
+ -C cluster0.cpu0.RVBAR=0 \
+ -C cluster0.granule_ownership_table_address=0x803f80000 \
+ -C cluster0.max_32bit_el=0 \
+ -C cluster0.has_rmode=1 \
+ -C bp.secureflashloader.fname="$bl1_path" \
+ -C bp.flashloader0.fname="$fip_path" \
+ --data cluster0.cpu0="$romfw_path"@0x2e000000
diff --git a/arch/Makefile b/arch/Makefile
@@ -0,0 +1,10 @@
+PROJECTDIR=..
+include $(PROJECTDIR)/scripts/rules.mk
+
+DIRS=arm64 amd64
+
+all:
+ +@cd $(ARCH) && $(MAKE)
+
+clean:
+ $(FORALL)
diff --git a/arch/amd64/Makefile b/arch/amd64/Makefile
@@ -0,0 +1,18 @@
+PROJECTDIR = ../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+ROMOBJS = crt-$(SYS).o panic.o arch.o rom.o $(SRCDIR)/romfw/builtin.o
+RAMOBJS = crt-$(SYS).o panic.o arch.o rom.o $(SRCDIR)/ramfw/builtin.o
+
+TARGET = $(BINDIR)/romfw.elf $(BINDIR)/ramfw.elf
+LIBS = -lrmu -lc
+LIBDEP = $(LIBDIR)/librmu.a $(LIBDIR)/libc.a
+
+
+all: $(TARGET)
+
+$(BINDIR)/romfw.elf: $(ROMOBJS) $(LIBDEP)
+ $(LD) $(RCODE_LDFLAGS) $(ROMOBJS) $(LIBS) -o $@
+
+$(BINDIR)/ramfw.elf: $(RAMOBJS) $(LIBDEP)
+ $(LD) $(RCODE_LDFLAGS) $(RAMOBJS) $(LIBS) -o $@
diff --git a/arch/amd64/arch.s b/arch/amd64/arch.s
@@ -0,0 +1 @@
+ .file "arch.s"
diff --git a/arch/amd64/crt-bsd.s b/arch/amd64/crt-bsd.s
@@ -0,0 +1,22 @@
+ .file "crt-bsd.s"
+
+ .bss
+ .globl _environ
+_environ:
+ .quad 0
+
+ .text
+ .align 8
+ .globl _start,_Exit
+_start:
+ movq %rsp,%rbp
+
+ /* load argc, argv, envp from stack */
+ movq (%rbp),%rdi /* argc */
+ leaq 8(%rbp),%rsi /* argv */
+ leaq 16(%rbp,%rax,8),%rcx /* envp = argv + 8*argc + 8 */
+ movq %rdx,_environ
+
+ call main
+ movl %eax,%edi
+ jmp _Exit
diff --git a/arch/amd64/crt-linux.s b/arch/amd64/crt-linux.s
@@ -0,0 +1,15 @@
+ .file "crt-linux.s"
+
+ .text
+ .globl _start,_Exit
+_start:
+ movq %rsp,%rbp
+
+ /* load argc, argv, envp from stack */
+ movq (%rbp),%rdi /* argc */
+ leaq 8(%rbp),%rsi /* argv */
+ leaq 16(%rbp,%rax,8),%rcx /* envp = argv + 8*argc + 8 */
+
+ call main
+ movl %eax,%edi
+ jmp _Exit
diff --git a/arch/amd64/panic.c b/arch/amd64/panic.c
@@ -0,0 +1,9 @@
+#include <rcode.h>
+
+void
+panic(const char *msg)
+{
+ dbg(msg);
+ for (;;)
+ ;
+}
diff --git a/arch/amd64/ram.c b/arch/amd64/ram.c
@@ -0,0 +1,18 @@
+#include <stdint.h>
+
+#include <rcode.h>
+
+int
+main(int argc, char *argv[])
+{
+ unsigned i, j;
+ Ctx ctx;
+
+ for (i = 0; i <= 9; i++) {
+ for (j = 0; j <= 14; j++) {
+ printk("%u\t%u\t", i, j);
+ rmc(i, j, &ctx);
+ }
+ }
+ return 0;
+}
diff --git a/arch/amd64/rom.c b/arch/amd64/rom.c
@@ -0,0 +1,18 @@
+#include <stdint.h>
+
+#include <rcode.h>
+
+int
+main(int argc, char *argv[])
+{
+ unsigned i, j;
+ Ctx ctx;
+
+ for (i = 0; i <= 9; i++) {
+ for (j = 0; j <= 14; j++) {
+ printk("%u\t%u\t", i, j);
+ rmc(i, j, &ctx);
+ }
+ }
+ return 0;
+}
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
@@ -0,0 +1,23 @@
+PROJECTDIR = ../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+ROMOBJS = rom-crt-$(SYS).o panic.o arch.o rom.o $(SRCDIR)/romfw/builtin.o
+RAMOBJS = ram-crt-$(SYS).o panic.o arch.o ram.o $(SRCDIR)/ramfw/builtin.o
+
+TARGET = $(BINDIR)/romfw.bin $(BINDIR)/ramfw.bin
+LIBS = -lrmu -lc
+LIBDEP = $(LIBDIR)/librmu.a $(LIBDIR)/libc.a
+
+all: $(TARGET)
+
+rom-crt-$(SYS).o: macros.s
+
+$(BINDIR)/romfw.elf: $(ROMOBJS) $(LIBDEP)
+ $(LD) $(RCODE_LDFLAGS) $(ROMOBJS) $(LIBS) -o $@
+
+$(BINDIR)/ramfw.elf: $(RAMOBJS) $(LIBDEP)
+ $(LD) $(RCODE_LDFLAGS) $(ROMOBJS) $(LIBS) -o $@
+
+clean:
+ rm -f $(TARGET:.bin=.elf)
+ rm -f $(TARGET:.bin=.tst)
diff --git a/arch/arm64/arch.s b/arch/arm64/arch.s
@@ -0,0 +1,33 @@
+ .file "arch.s"
+
+ .text
+ .globl panic,panic_helper
+ .align 2
+panic: stp x1,x0,[sp,#-16]!
+ stp x3,x2,[sp,#-16]!
+ stp x5,x4,[sp,#-16]!
+ stp x7,x6,[sp,#-16]!
+ stp x9,x8,[sp,#-16]!
+ stp x11,x10,[sp,#-16]!
+ stp x13,x12,[sp,#-16]!
+ stp x15,x14,[sp,#-16]!
+ stp x17,x16,[sp,#-16]!
+ stp x19,x18,[sp,#-16]!
+ stp x21,x20,[sp,#-16]!
+ stp x23,x22,[sp,#-16]!
+ stp x25,x24,[sp,#-16]!
+ stp x27,x26,[sp,#-16]!
+ stp x29,x28,[sp,#-16]!
+ mov x1,sp
+ stp x1,x30,[sp,#-16]!
+
+ mrs x3,S3_6_C4_C0_6 /* SPSR_R */
+ mrs x2,S3_6_C4_C0_3 /* ELR_R */
+ stp x3,x2,[sp,#-16]!
+
+ mrs x1,S3_6_C6_C0_6 /* FAR_R */
+ mrs x0,S3_6_C5_C2_6 /* ESR_R */
+ stp x1,x0,[sp,#-16]!
+
+ mov x1,sp
+ b cpanic
diff --git a/arch/arm64/macros.s b/arch/arm64/macros.s
@@ -0,0 +1,65 @@
+.macro vempty
+ .align 3
+ adr x0,badtrap
+ b panic
+.endm
+
+.macro vector name
+ .align 3
+ b \name
+.endm
+
+.macro handler target
+ stp x1,x0,[sp,#-16]!
+ stp x3,x2,[sp,#-16]!
+ stp x5,x4,[sp,#-16]!
+ stp x7,x6,[sp,#-16]!
+ stp x9,x8,[sp,#-16]!
+ stp x11,x10,[sp,#-16]!
+ stp x13,x12,[sp,#-16]!
+ stp x15,x14,[sp,#-16]!
+ stp x17,x16,[sp,#-16]!
+ stp x19,x18,[sp,#-16]!
+ stp x21,x20,[sp,#-16]!
+ stp x23,x22,[sp,#-16]!
+ stp x25,x24,[sp,#-16]!
+ stp x27,x26,[sp,#-16]!
+ stp x29,x28,[sp,#-16]!
+ stp xzr,x30,[sp,#-16]! /* SP = 0, only useful in panic() */
+
+ mrs x1,S3_6_C4_C0_6 /* SPSR_R */
+ mrs x0,S3_6_C4_C0_3 /* ELR_R */
+ stp x1,x0,[sp,#-16]!
+
+ mrs x1,S3_6_C6_C0_6 /* FAR_R */
+ mrs x0,S3_6_C5_C2_6 /* ESR_R */
+ stp x1,x0,[sp,#-16]!
+
+ mov x0,sp
+ bl \target
+
+ ldp x1,x0,[sp],#16
+ msr S3_6_C6_C0_6,x1 /* FAR_R */
+ msr S3_6_C5_C2_6,x0 /* ESR_R */
+
+ ldp x1,x0,[sp],#16
+ msr S3_6_C4_C0_6,x1 /* SPSR_R */
+ msr S3_6_C4_C0_3,x0 /* ELR_R */
+
+ ldp xzr,x30,[sp],#16
+ ldp x29,x28,[sp],#16
+ ldp x27,x26,[sp],#16
+ ldp x25,x24,[sp],#16
+ ldp x23,x22,[sp],#16
+ ldp x21,x20,[sp],#16
+ ldp x19,x18,[sp],#16
+ ldp x17,x16,[sp],#16
+ ldp x15,x14,[sp],#16
+ ldp x13,x12,[sp],#16
+ ldp x11,x10,[sp],#16
+ ldp x9,x8,[sp],#16
+ ldp x7,x6,[sp],#16
+ ldp x5,x4,[sp],#16
+ ldp x3,x2,[sp],#16
+ ldp x1,x0,[sp],#16
+.endm
diff --git a/arch/arm64/panic.c b/arch/arm64/panic.c
@@ -0,0 +1,42 @@
+#include <rcode.h>
+#include <arch/machine.h>
+
+void
+cpanic(const char *msg, struct trapframe *fp)
+{
+ struct bssmap *bm = bss;
+ void **bp;
+
+ if (bm->in_panic)
+ goto htl;
+
+ bm->in_panic = 1;
+ printk("panic: %s\n"
+ "x0=%llx\tx1=%llx\tx2=%llx\tx3=%llx\n"
+ "x4=%llx\tx5=%llx\tx6=%llx\tx7=%llx\n"
+ "x8=%llx\tx9=%llx\tx10=%llx\tx11=%llx\n"
+ "x12=%llx\tx13=%llx\tx14=%llx\tx15=%llx\n"
+ "x16=%llx\tx17=%llx\tx18=%llx\tx19=%llx\n"
+ "x20=%llx\tx21=%llx\tx22=%llx\tx23=%llx\n"
+ "x24=%llx\tx25=%llx\tx26=%llx\tx27=%llx\n"
+ "x28=%llx\tx29=%llx\tx30=%llx\telr=%llx\n"
+ "spsr=%llx\tesr=%llx\tfar=%llx\n"
+ "sp=%llx\n"
+ "stack trace:\n",
+ msg,
+ fp->x0, fp->x1, fp->x2, fp->x3,
+ fp->x4, fp->x5, fp->x6, fp->x7,
+ fp->x8, fp->x9, fp->x10, fp->x11,
+ fp->x12, fp->x13, fp->x14, fp->x15,
+ fp->x16, fp->x17, fp->x18, fp->x19,
+ fp->x20, fp->x21, fp->x22, fp->x23,
+ fp->x24, fp->x25, fp->x26, fp->x27,
+ fp->x28, fp->x29, fp->x30, fp->elr,
+ fp->spsr, fp->esr, fp->far, fp->sp);
+
+ for (bp = (void **) fp->x29; *bp; bp = (void **) *bp)
+ printk("%llx\n", bp[1]);
+htl:
+ for (;;)
+ ;
+}
diff --git a/arch/arm64/ram-crt-linux.s b/arch/arm64/ram-crt-linux.s
@@ -0,0 +1,7 @@
+ .file "ram-crt-linux.s"
+
+ .text
+ .globl _start
+_start:
+ bl main
+ b _Exit
diff --git a/arch/arm64/ram-crt-none.s b/arch/arm64/ram-crt-none.s
@@ -0,0 +1,68 @@
+ .file "rom-crt-none.s"
+
+ .include "macros.s"
+
+/* TODO: extract data section address from RSCB */
+BSS = 0x2E00F000
+BSSSIZ = 1024
+PAGESIZ = 4096
+
+ .text
+ .globl _start
+_start:
+ adr x0,vectbl
+ msr S3_6_C12_C0_6,x0 /* VBAR_R */
+ isb
+
+ /* Stack grows down towards BSS */
+ msr spsel,#1
+ ldr x0,=BSS
+ mov x1,#(PAGESIZ-16)
+ add x0,x0,x1
+ mov sp,x0
+ mov x29,sp
+ stp xzr,xzr,[x29] /* zero FP/LR to terminate backtrace */
+
+ ldr x0,=BSS
+ mov x1,#0
+ mov x2,BSSSIZ
+ bl memset
+
+ bl _uart_init
+
+ mrs x0,rvbar_el3
+ handler main
+ eret
+
+/* Top level AArch32/AArch64 Sync exception handler */
+_synchdl:
+ handler synchdl
+ eret
+
+ .align 11
+vectbl:
+ /* Current EL with SP0 */
+ vempty /* Sync */
+ vempty /* IRQ/vIRQ */
+ vempty /* FIQ/vFIQ */
+ vempty /* SError/VSError */
+
+ /* Current EL with SPx */
+ vempty /* Sync */
+ vempty /* IRQ/vIRQ */
+ vempty /* FIQ/vFIQ */
+ vempty /* SError/VSError */
+
+ /* Lower EL using AArch64 */
+ vector _synchdl /* Sync */
+ vempty /* IRQ/vIRQ */
+ vempty /* FIQ/vFIQ */
+ vempty /* SError/VSError */
+
+ /* Lower EL using AArch32 */
+ vector _synchdl /* Sync */
+ vempty /* IRQ/vIRQ */
+ vempty /* FIQ/vFIQ */
+ vempty /* SError/VSError */
+
+badtrap: .asciz "bad exception"
diff --git a/arch/arm64/ram.c b/arch/arm64/ram.c
@@ -0,0 +1,18 @@
+#include <stdint.h>
+
+#include <rcode.h>
+
+int
+main(int argc, char *argv[])
+{
+ unsigned i, j;
+ Ctx ctx;
+
+ for (i = 0; i <= 9; i++) {
+ for (j = 0; j <= 14; j++) {
+ printk("%u\t%u\t", i, j);
+ rmc(i, j, &ctx);
+ }
+ }
+ return 0;
+}
diff --git a/arch/arm64/rom-crt-linux.s b/arch/arm64/rom-crt-linux.s
@@ -0,0 +1,7 @@
+ .file "rom-crt-linux.s"
+
+ .text
+ .globl _start
+_start:
+ bl main
+ b _Exit
diff --git a/arch/arm64/rom-crt-none.s b/arch/arm64/rom-crt-none.s
@@ -0,0 +1,68 @@
+ .file "rom-crt-none.s"
+
+ .include "macros.s"
+
+/* TODO: extract data section address from RSCB */
+BSS = 0x2E00F000
+BSSSIZ = 1024
+PAGESIZ = 4096
+
+ .text
+ .globl _start
+_start:
+ adr x0,vectbl
+ msr S3_6_C12_C0_6,x0 /* VBAR_R */
+ isb
+
+ /* Stack grows down towards BSS */
+ msr spsel,#1
+ ldr x0,=BSS
+ mov x1,#(PAGESIZ-16)
+ add x0,x0,x1
+ mov sp,x0
+ mov x29,sp
+ stp xzr,xzr,[x29] /* zero FP/LR to terminate backtrace */
+
+ ldr x0,=BSS
+ mov x1,#0
+ mov x2,BSSSIZ
+ bl memset
+
+ bl _uart_init
+
+ mrs x0,rvbar_el3
+ handler main
+ eret
+
+/* Top level AArch32/AArch64 Sync exception handler */
+_synchdl:
+ handler synchdl
+ eret
+
+ .align 11
+vectbl:
+ /* Current EL with SP0 */
+ vempty /* Sync */
+ vempty /* IRQ/vIRQ */
+ vempty /* FIQ/vFIQ */
+ vempty /* SError/VSError */
+
+ /* Current EL with SPx */
+ vempty /* Sync */
+ vempty /* IRQ/vIRQ */
+ vempty /* FIQ/vFIQ */
+ vempty /* SError/VSError */
+
+ /* Lower EL using AArch64 */
+ vector _synchdl /* Sync */
+ vempty /* IRQ/vIRQ */
+ vempty /* FIQ/vFIQ */
+ vempty /* SError/VSError */
+
+ /* Lower EL using AArch32 */
+ vector _synchdl /* Sync */
+ vempty /* IRQ/vIRQ */
+ vempty /* FIQ/vFIQ */
+ vempty /* SError/VSError */
+
+badtrap: .asciz "bad exception"
diff --git a/arch/arm64/rom.c b/arch/arm64/rom.c
@@ -0,0 +1,23 @@
+#include <string.h>
+
+#include <arch/machine.h>
+#include <rcode.h>
+
+void
+synchdl(struct trapframe *fp)
+{
+ dbg("sync handler\n");
+}
+
+int
+main(struct trapframe *fp)
+{
+ unsigned long long rvbar_el3;
+
+ rvbar_el3 = fp->x0;
+ /* Clear all regs to avoid leaking info to EL3h */
+ memset(fp, 0, sizeof(*fp));
+ fp->elr = rvbar_el3;
+ fp->spsr = 0xf << 6 | 0xd;
+ return 0;
+}
diff --git a/config/amd64-bsd.mk b/config/amd64-bsd.mk
@@ -0,0 +1,8 @@
+ARCH = amd64
+SYSCFLAGS = -g -static -nostdinc -ffreestanding -std=c99 -fno-stack-protector -MD -Wall
+SYSLDFLAGS = -static -z nodefaultlib
+COMP = gcc
+ASM = as
+LINKER = ld
+SYS = bsd
+CROSS_COMPILE =
diff --git a/config/amd64-linux.mk b/config/amd64-linux.mk
@@ -0,0 +1,8 @@
+ARCH = amd64
+SYSCFLAGS = -g -static -nostdinc -ffreestanding -std=c99 -fno-stack-protector -MD -Wall
+SYSLDFLAGS = -static -z nodefaultlib
+COMP = gcc
+ASM = as
+LINKER = ld
+SYS = linux
+CROSS_COMPILE =
diff --git a/config/arm64-linux.mk b/config/arm64-linux.mk
@@ -0,0 +1,10 @@
+ARCH = arm64
+SYSCFLAGS = -g -static -nostdinc -ffreestanding -std=c99 -fno-stack-protector -MD -Wall
+SYSLDFLAGS = -static -z nodefaultlib
+CROSS_COMPILE = aarch64-linux-gnu-
+SYS=linux
+COMP = gcc
+ASM = as
+LINKER = ld
+EMU = qemu-aarch64-static
+OBJCOPY = objcopy
diff --git a/config/arm64-none.mk b/config/arm64-none.mk
@@ -0,0 +1,9 @@
+ARCH = arm64
+SYSCFLAGS = -g -static -nostdinc -ffreestanding -std=c99 -mgeneral-regs-only -fno-stack-protector -MD -Wall
+SYSLDFLAGS = -static -z nodefaultlib -Ttext=0
+CROSS_COMPILE = aarch64-elf-
+SYS=none
+COMP = gcc
+ASM = as
+LINKER = ld
+OBJCOPY = objcopy
diff --git a/include/assert.h b/include/assert.h
@@ -0,0 +1,10 @@
+
+void __assert(char *exp, char *file, long line);
+
+#undef assert
+#ifndef NDEBUG
+# define assert(exp) ((exp) ? (void) 0 : __assert(#exp, __FILE__, __LINE__))
+#else
+# define assert(exp) ((void)0)
+#endif
+
diff --git a/include/bits/amd64/arch/limits.h b/include/bits/amd64/arch/limits.h
@@ -0,0 +1,17 @@
+#define SCHAR_MAX 0x7F
+#define SCHAR_MIN (-SCHAR_MIN-1)
+#define CHAR_MAX 0x7F
+#define CHAR_MIN (-CHAR_MAX-1)
+#define UCHAR_MAX 0xFF
+#define SHRT_MAX 0x7FFF
+#define SHRT_MIN (-SHRT_MAX-1)
+#define USHRT_MAX 0xFFFF
+#define INT_MAX 0x7FFFFFFF
+#define INT_MIN (-INT_MAX-1)
+#define UINT_MAX 0xFFFFFFFF
+#define LONG_MAX 0x7FFFFFFFFFFFFFFF
+#define LONG_MIN (-LONG_MAX-1)
+#define ULONG_MAX 0xFFFFFFFFFFFFFFFF
+#define LLONG_MAX 0x7FFFFFFFFFFFFFFF
+#define LLONG_MIN (-LLONG_MAX-1)
+#define ULLONG_MAX 0xFFFFFFFFFFFFFFFF
diff --git a/include/bits/amd64/arch/setjmp.h b/include/bits/amd64/arch/setjmp.h
@@ -0,0 +1 @@
+typedef unsigned long long jmp_buf[8];
diff --git a/include/bits/amd64/arch/stddef.h b/include/bits/amd64/arch/stddef.h
@@ -0,0 +1,14 @@
+#ifndef _SIZET
+typedef unsigned long size_t;
+#define _SIZET
+#endif
+
+#ifndef _WCHAR_T
+typedef int wchar_t;
+#define _WCHAR_T
+#endif
+
+#ifndef _PTRDIFF_T
+typedef long ptrdiff_t;
+#define _PTRDIFF_T
+#endif
diff --git a/include/bits/amd64/arch/stdint.h b/include/bits/amd64/arch/stdint.h
@@ -0,0 +1,115 @@
+#define INT8_MAX 0x7F
+#define INT8_MIN (-INT8_MAX-1)
+#define UINT8_MAX 0xFF
+
+#define INT16_MAX 0x7FFF
+#define INT16_MIN (-INT16_MAX-1)
+#define UINT16_MAX 0xFFFF
+
+#define INT32_MAX 0x7FFFFFFF
+#define INT32_MIN (-INT32_MAX-1)
+#define UINT32_MAX 0xFFFFFFFF
+
+#define INT64_MAX 0x7FFFFFFFFFFFFFFF
+#define INT64_MIN (-INT64_MAX-1)
+#define UINT64_MAX 0xFFFFFFFFFFFFFFFF
+
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+#define INT_FAST8_MIN INT32_MIN
+#define INT_FAST8_MAX INT32_MAX
+#define UINT_FAST8_MAX UINT32_MAX
+
+#define INT_FAST16_MIN INT32_MIN
+#define INT_FAST16_MAX INT32_MAX
+#define UINT_FAST16_MAX UINT32_MAX
+
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+#define INTPTR_MIN INT64_MIN
+#define INTPTR_MAX INT64_MAX
+#define UINTPTR_MAX UINT64_MAX
+
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+#define PTRDIFF_MIN INT64_MIN
+#define PTRDIFF_MAX INT64_MAX
+
+#define SIG_ATOMIC_MIN INT32_MIN
+#define SIG_ATOMIC_MAX INT32_MAX
+
+#define SIZE_MAX UINT64_MAX
+
+#define WCHAR_MIN INT32_MIN
+#define WCHAR_MAX INT32_MAX
+
+#define INT8_C(x) x
+#define INT16_C(x) x
+#define INT32_C(x) x
+#define INT64_C(x) x ## L
+
+#define UINT8_C(x) x
+#define UINT16_C(x) x
+#define UINT32_C(x) x ## U
+#define UINT64_C(x) x ## UL
+
+#define INTMAX_C(x) x ## L
+#define UINTMAX_C(x) x ## UL
+
+typedef signed char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+typedef long int64_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned uint32_t;
+typedef unsigned long uint64_t;
+
+typedef signed char int8_least_t;
+typedef short int16_least_t;
+typedef int int32_least_t;
+typedef long int64_least_t;
+
+typedef unsigned char uint8_least_t;
+typedef unsigned short uint16_least_t;
+typedef unsigned uint32_least_t;
+typedef unsigned long uint64_least_t;
+
+typedef int int8_fast_t;
+typedef int int16_fast_t;
+typedef int int32_fast_t;
+typedef long int64_fast_t;
+
+typedef unsigned uint8_fast_t;
+typedef unsigned uint16_fast_t;
+typedef unsigned uint32_fast_t;
+typedef unsigned long uint64_fast_t;
+
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+
+typedef long intmax_t;
+typedef unsigned long uintmax_t;
diff --git a/include/bits/amd64/arch/stdio.h b/include/bits/amd64/arch/stdio.h
@@ -0,0 +1,15 @@
+#ifndef _SIZET
+typedef unsigned long size_t;
+#define _SIZET
+#endif
+
+#define BUFSIZ 512
+#define FILENAME_MAX 256
+#define FOPEN_MAX 16
+
+#define TMP_MAX 25
+#define L_tmpnam 256
+
+#define _TMPNAME "/tmp/tmp.0000000"
+
+typedef int fpos_t;
diff --git a/include/bits/amd64/arch/stdlib.h b/include/bits/amd64/arch/stdlib.h
@@ -0,0 +1,14 @@
+#ifndef _SIZET
+typedef unsigned long size_t;
+#define _SIZET
+#endif
+
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+
+#ifndef _WCHAR_T
+typedef int wchar_t;
+#define _WCHAR_T
+#endif
+
+#define _ALIGNTYPE long double
diff --git a/include/bits/amd64/arch/string.h b/include/bits/amd64/arch/string.h
@@ -0,0 +1,3 @@
+#ifndef _SIZET
+typedef unsigned long size_t;
+#endif
diff --git a/include/bits/arm64/arch/limits.h b/include/bits/arm64/arch/limits.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#define SCHAR_MAX 0x7F
+#define SCHAR_MIN (-SCHAR_MIN - 1)
+#define CHAR_MAX 0x7F
+#define CHAR_MIN (-CHAR_MAX - 1)
+#define UCHAR_MAX 0xFFU
+#define SHRT_MAX 0x7FFF
+#define SHRT_MIN (-SHRT_MAX - 1)
+#define USHRT_MAX 0xFFFFU
+#define INT_MAX 0x7FFFFFFF
+#define INT_MIN (-INT_MAX - 1)
+#define UINT_MAX 0xFFFFFFFFU
+#define LONG_MAX 0x7FFFFFFFFFFFFFFFL
+#define LONG_MIN (-LONG_MAX - 1L)
+#define ULONG_MAX 0xFFFFFFFFFFFFFFFFUL
+#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL
+#define LLONG_MIN (-LLONG_MAX - 1LL)
+#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL
diff --git a/include/bits/arm64/arch/machine.h b/include/bits/arm64/arch/machine.h
@@ -0,0 +1,17 @@
+struct trapframe {
+ unsigned long long far;
+ unsigned long long esr;
+ unsigned long long spsr;
+ unsigned long long elr;
+ unsigned long long sp;
+ unsigned long long x30,x29,x28,x27;
+ unsigned long long x26,x25,x24,x23;
+ unsigned long long x22,x21,x20,x19;
+ unsigned long long x18,x17,x16,x15;
+ unsigned long long x14,x13,x12,x11;
+ unsigned long long x10,x9,x8,x7;
+ unsigned long long x6,x5,x4,x3;
+ unsigned long long x2,x1,x0;
+};
+
+extern void cpanic(const char *msg, struct trapframe *fp);
diff --git a/include/bits/arm64/arch/setjmp.h b/include/bits/arm64/arch/setjmp.h
@@ -0,0 +1 @@
+typedef unsigned long long jmp_buf[22];
diff --git a/include/bits/arm64/arch/stddef.h b/include/bits/arm64/arch/stddef.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SIZET_
+typedef unsigned long size_t;
+#define SIZET_
+#endif
+
+#ifndef _PTRDIFF_T
+typedef long ptrdiff_t;
+#define _PTRDIFF_T
+#endif
diff --git a/include/bits/arm64/arch/stdint.h b/include/bits/arm64/arch/stdint.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#define INT8_MAX 0x7F
+#define INT8_MIN (-INT8_MAX - 1)
+#define UINT8_MAX 0xFFU
+
+#define INT16_MAX 0x7FFF
+#define INT16_MIN (-INT16_MAX - 1)
+#define UINT16_MAX 0xFFFFU
+
+#define INT32_MAX 0x7FFFFFFF
+#define INT32_MIN (-INT32_MAX - 1)
+#define UINT32_MAX 0xFFFFFFFFU
+
+#define INT64_MAX 0x7FFFFFFFFFFFFFFFLL
+#define INT64_MIN (-INT64_MAX - 1LL)
+#define UINT64_MAX 0xFFFFFFFFFFFFFFFFULL
+
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+#define INT_FAST8_MIN INT32_MIN
+#define INT_FAST8_MAX INT32_MAX
+#define UINT_FAST8_MAX UINT32_MAX
+
+#define INT_FAST16_MIN INT32_MIN
+#define INT_FAST16_MAX INT32_MAX
+#define UINT_FAST16_MAX UINT32_MAX
+
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+#define INTPTR_MIN INT64_MIN
+#define INTPTR_MAX INT64_MAX
+#define UINTPTR_MAX UINT64_MAX
+
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+#define PTRDIFF_MIN INT64_MIN
+#define PTRDIFF_MAX INT64_MAX
+
+#define SIZE_MAX UINT64_MAX
+
+#define INT8_C(x) x
+#define INT16_C(x) x
+#define INT32_C(x) x
+#define INT64_C(x) x ## LL
+
+#define UINT8_C(x) x
+#define UINT16_C(x) x
+#define UINT32_C(x) x ## U
+#define UINT64_C(x) x ## ULL
+
+#define INTMAX_C(x) x ## L
+#define UINTMAX_C(x) x ## ULL
+
+typedef signed char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+typedef long long int64_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_least_t;
+typedef short int16_least_t;
+typedef int int32_least_t;
+typedef long long int64_least_t;
+
+typedef unsigned char uint8_least_t;
+typedef unsigned short uint16_least_t;
+typedef unsigned int uint32_least_t;
+typedef unsigned long long uint64_least_t;
+
+typedef int int8_fast_t;
+typedef int int16_fast_t;
+typedef int int32_fast_t;
+typedef long long int64_fast_t;
+
+typedef unsigned int uint8_fast_t;
+typedef unsigned int uint16_fast_t;
+typedef unsigned int uint32_fast_t;
+typedef unsigned long long uint64_fast_t;
+
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+
+typedef long intmax_t;
+typedef unsigned long uintmax_t;
diff --git a/include/bits/arm64/arch/stdio.h b/include/bits/arm64/arch/stdio.h
@@ -0,0 +1,15 @@
+#ifndef _SIZET
+typedef unsigned long size_t;
+#define _SIZET
+#endif
+
+#define BUFSIZ 512
+#define FILENAME_MAX 256
+#define FOPEN_MAX 16
+
+#define TMP_MAX 25
+#define L_tmpnam 256
+
+#define _TMPNAME "/tmp/tmp.0000000"
+
+typedef int fpos_t;
diff --git a/include/bits/arm64/arch/stdlib.h b/include/bits/arm64/arch/stdlib.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SIZET_
+typedef unsigned long size_t;
+#define SIZET_
+#endif
+
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
diff --git a/include/bits/arm64/arch/string.h b/include/bits/arm64/arch/string.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SIZET_
+typedef unsigned long size_t;
+#define SIZET_
+#endif
diff --git a/include/bits/bsd/sys/errno.h b/include/bits/bsd/sys/errno.h
@@ -0,0 +1,98 @@
+#define EWOULDBLOCK EAGAIN
+#define EPERM 1
+#define ENOENT 2
+#define ESRCH 3
+#define EINTR 4
+#define EIO 5
+#define ENXIO 6
+#define E2BIG 7
+#define ENOEXEC 8
+#define EBADF 9
+#define ECHILD 10
+#define EDEADLK 11
+#define ENOMEM 12
+#define EACCES 13
+#define EFAULT 14
+#define ENOTBLK 15
+#define EBUSY 16
+#define EEXIST 17
+#define EXDEV 18
+#define ENODEV 19
+#define ENOTDIR 20
+#define EISDIR 21
+#define EINVAL 22
+#define ENFILE 23
+#define EMFILE 24
+#define ENOTTY 25
+#define ETXTBSY 26
+#define EFBIG 27
+#define ENOSPC 28
+#define ESPIPE 29
+#define EROFS 30
+#define EMLINK 31
+#define EPIPE 32
+#define EDOM 33
+#define ERANGE 34
+#define EAGAIN 35
+#define EINPROGRESS 36
+#define EALREADY 37
+#define ENOTSOCK 38
+#define EDESTADDRREQ 39
+#define EMSGSIZE 40
+#define EPROTOTYPE 41
+#define ENOPROTOOPT 42
+#define EPROTONOSUPPORT 43
+#define ESOCKTNOSUPPORT 44
+#define EOPNOTSUPP 45
+#define EPFNOSUPPORT 46
+#define EAFNOSUPPORT 47
+#define EADDRINUSE 48
+#define EADDRNOTAVAIL 49
+#define ENETDOWN 50
+#define ENETUNREACH 51
+#define ENETRESET 52
+#define ECONNABORTED 53
+#define ECONNRESET 54
+#define ENOBUFS 55
+#define EISCONN 56
+#define ENOTCONN 57
+#define ESHUTDOWN 58
+#define ETOOMANYREFS 59
+#define ETIMEDOUT 60
+#define ECONNREFUSED 61
+#define ELOOP 62
+#define ENAMETOOLONG 63
+#define EHOSTDOWN 64
+#define EHOSTUNREACH 65
+#define ENOTEMPTY 66
+#define EPROCLIM 67
+#define EUSERS 68
+#define EDQUOT 69
+#define ESTALE 70
+#define EREMOTE 71
+#define EBADRPC 72
+#define ERPCMISMATCH 73
+#define EPROGUNAVAIL 74
+#define EPROGMISMATCH 75
+#define EPROCUNAVAIL 76
+#define ENOLCK 77
+#define ENOSYS 78
+#define EFTYPE 79
+#define EAUTH 80
+#define ENEEDAUTH 81
+#define EIDRM 82
+#define ENOMSG 83
+#define EOVERFLOW 84
+#define EILSEQ 85
+#define ENOTSUP 86
+#define ECANCELED 87
+#define EBADMSG 88
+#define ENODATA 89
+#define ENOSR 90
+#define ENOSTR 91
+#define ETIME 92
+#define ENOATTR 93
+#define EMULTIHOP 94
+#define ENOLINK 95
+#define ELAST 96
+#define EPROTO 96
diff --git a/include/bits/bsd/sys/signal.h b/include/bits/bsd/sys/signal.h
@@ -0,0 +1,27 @@
+typedef int sig_atomic_t;
+
+#define SIG_ERR ((void (*)(int))-1)
+#define SIG_DFL ((void (*)(int)) 0)
+#define SIG_IGN ((void (*)(int)) 1)
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGABRT 6
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGSSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+
+#define __NR_SIGNALS 23
diff --git a/include/bits/linux/sys/errno.h b/include/bits/linux/sys/errno.h
@@ -0,0 +1,131 @@
+#define EPERM 1
+#define ENOENT 2
+#define ESRCH 3
+#define EINTR 4
+#define EIO 5
+#define ENXIO 6
+#define E2BIG 7
+#define ENOEXEC 8
+#define EBADF 9
+#define ECHILD 10
+#define EAGAIN 11
+#define ENOMEM 12
+#define EACCES 13
+#define EFAULT 14
+#define ENOTBLK 15
+#define EBUSY 16
+#define EEXIST 17
+#define EXDEV 18
+#define ENODEV 19
+#define ENOTDIR 20
+#define EISDIR 21
+#define EINVAL 22
+#define ENFILE 23
+#define EMFILE 24
+#define ENOTTY 25
+#define ETXTBSY 26
+#define EFBIG 27
+#define ENOSPC 28
+#define ESPIPE 29
+#define EROFS 30
+#define EMLINK 31
+#define EPIPE 32
+#define EDOM 33
+#define ERANGE 34
+#define EDEADLK 35
+#define ENAMETOOLONG 36
+#define ENOLCK 37
+#define ENOSYS 38
+#define ENOTEMPTY 39
+#define ELOOP 40
+#define ENOMSG 42
+#define EIDRM 43
+#define ECHRNG 44
+#define EL2NSYNC 45
+#define EL3HLT 46
+#define EL3RST 47
+#define ELNRNG 48
+#define EUNATCH 49
+#define ENOCSI 50
+#define EL2HLT 51
+#define EBADE 52
+#define EBADR 53
+#define EXFULL 54
+#define ENOANO 55
+#define EBADRQC 56
+#define EBADSLT 57
+#define EBFONT 59
+#define ENOSTR 60
+#define ENODATA 61
+#define ETIME 62
+#define ENOSR 63
+#define ENONET 64
+#define ENOPKG 65
+#define EREMOTE 66
+#define ENOLINK 67
+#define EADV 68
+#define ESRMNT 69
+#define ECOMM 70
+#define EPROTO 71
+#define EMULTIHOP 72
+#define EDOTDOT 73
+#define EBADMSG 74
+#define EOVERFLOW 75
+#define ENOTUNIQ 76
+#define EBADFD 77
+#define EREMCHG 78
+#define ELIBACC 79
+#define ELIBBAD 80
+#define ELIBSCN 81
+#define ELIBMAX 82
+#define ELIBEXEC 83
+#define EILSEQ 84
+#define ERESTART 85
+#define ESTRPIPE 86
+#define EUSERS 87
+#define ENOTSOCK 88
+#define EDESTADDRREQ 89
+#define EMSGSIZE 90
+#define EPROTOTYPE 91
+#define ENOPROTOOPT 92
+#define EPROTONOSUPPORT 93
+#define ESOCKTNOSUPPORT 94
+#define EOPNOTSUPP 95
+#define EPFNOSUPPORT 96
+#define EAFNOSUPPORT 97
+#define EADDRINUSE 98
+#define EADDRNOTAVAIL 99
+#define ENETDOWN 100
+#define ENETUNREACH 101
+#define ENETRESET 102
+#define ECONNABORTED 103
+#define ECONNRESET 104
+#define ENOBUFS 105
+#define EISCONN 106
+#define ENOTCONN 107
+#define ESHUTDOWN 108
+#define ETOOMANYREFS 109
+#define ETIMEDOUT 110
+#define ECONNREFUSED 111
+#define EHOSTDOWN 112
+#define EHOSTUNREACH 113
+#define EALREADY 114
+#define EINPROGRESS 115
+#define ESTALE 116
+#define EUCLEAN 117
+#define ENOTNAM 118
+#define ENAVAIL 119
+#define EISNAM 120
+#define EREMOTEIO 121
+#define EDQUOT 122
+#define ENOMEDIUM 123
+#define EMEDIUMTYPE 124
+#define ECANCELED 125
+#define ENOKEY 126
+#define EKEYEXPIRED 127
+#define EKEYREVOKED 128
+#define EKEYREJECTED 129
+#define EOWNERDEAD 130
+#define ENOTRECOVERABLE 131
+#define ERFKILL 132
+#define EHWPOISON 133
diff --git a/include/bits/linux/sys/signal.h b/include/bits/linux/sys/signal.h
@@ -0,0 +1,27 @@
+typedef int sig_atomic_t;
+
+#define SIG_ERR ((void (*)(int))-1)
+#define SIG_DFL ((void (*)(int)) 0)
+#define SIG_IGN ((void (*)(int)) 1)
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGABRT 6
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGSSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+
+#define __NR_SIGNALS 23
diff --git a/include/bits/none/sys/errno.h b/include/bits/none/sys/errno.h
@@ -0,0 +1,131 @@
+#define EPERM 1
+#define ENOENT 2
+#define ESRCH 3
+#define EINTR 4
+#define EIO 5
+#define ENXIO 6
+#define E2BIG 7
+#define ENOEXEC 8
+#define EBADF 9
+#define ECHILD 10
+#define EAGAIN 11
+#define ENOMEM 12
+#define EACCES 13
+#define EFAULT 14
+#define ENOTBLK 15
+#define EBUSY 16
+#define EEXIST 17
+#define EXDEV 18
+#define ENODEV 19
+#define ENOTDIR 20
+#define EISDIR 21
+#define EINVAL 22
+#define ENFILE 23
+#define EMFILE 24
+#define ENOTTY 25
+#define ETXTBSY 26
+#define EFBIG 27
+#define ENOSPC 28
+#define ESPIPE 29
+#define EROFS 30
+#define EMLINK 31
+#define EPIPE 32
+#define EDOM 33
+#define ERANGE 34
+#define EDEADLK 35
+#define ENAMETOOLONG 36
+#define ENOLCK 37
+#define ENOSYS 38
+#define ENOTEMPTY 39
+#define ELOOP 40
+#define ENOMSG 42
+#define EIDRM 43
+#define ECHRNG 44
+#define EL2NSYNC 45
+#define EL3HLT 46
+#define EL3RST 47
+#define ELNRNG 48
+#define EUNATCH 49
+#define ENOCSI 50
+#define EL2HLT 51
+#define EBADE 52
+#define EBADR 53
+#define EXFULL 54
+#define ENOANO 55
+#define EBADRQC 56
+#define EBADSLT 57
+#define EBFONT 59
+#define ENOSTR 60
+#define ENODATA 61
+#define ETIME 62
+#define ENOSR 63
+#define ENONET 64
+#define ENOPKG 65
+#define EREMOTE 66
+#define ENOLINK 67
+#define EADV 68
+#define ESRMNT 69
+#define ECOMM 70
+#define EPROTO 71
+#define EMULTIHOP 72
+#define EDOTDOT 73
+#define EBADMSG 74
+#define EOVERFLOW 75
+#define ENOTUNIQ 76
+#define EBADFD 77
+#define EREMCHG 78
+#define ELIBACC 79
+#define ELIBBAD 80
+#define ELIBSCN 81
+#define ELIBMAX 82
+#define ELIBEXEC 83
+#define EILSEQ 84
+#define ERESTART 85
+#define ESTRPIPE 86
+#define EUSERS 87
+#define ENOTSOCK 88
+#define EDESTADDRREQ 89
+#define EMSGSIZE 90
+#define EPROTOTYPE 91
+#define ENOPROTOOPT 92
+#define EPROTONOSUPPORT 93
+#define ESOCKTNOSUPPORT 94
+#define EOPNOTSUPP 95
+#define EPFNOSUPPORT 96
+#define EAFNOSUPPORT 97
+#define EADDRINUSE 98
+#define EADDRNOTAVAIL 99
+#define ENETDOWN 100
+#define ENETUNREACH 101
+#define ENETRESET 102
+#define ECONNABORTED 103
+#define ECONNRESET 104
+#define ENOBUFS 105
+#define EISCONN 106
+#define ENOTCONN 107
+#define ESHUTDOWN 108
+#define ETOOMANYREFS 109
+#define ETIMEDOUT 110
+#define ECONNREFUSED 111
+#define EHOSTDOWN 112
+#define EHOSTUNREACH 113
+#define EALREADY 114
+#define EINPROGRESS 115
+#define ESTALE 116
+#define EUCLEAN 117
+#define ENOTNAM 118
+#define ENAVAIL 119
+#define EISNAM 120
+#define EREMOTEIO 121
+#define EDQUOT 122
+#define ENOMEDIUM 123
+#define EMEDIUMTYPE 124
+#define ECANCELED 125
+#define ENOKEY 126
+#define EKEYEXPIRED 127
+#define EKEYREVOKED 128
+#define EKEYREJECTED 129
+#define EOWNERDEAD 130
+#define ENOTRECOVERABLE 131
+#define ERFKILL 132
+#define EHWPOISON 133
diff --git a/include/bits/none/sys/signal.h b/include/bits/none/sys/signal.h
@@ -0,0 +1,27 @@
+typedef int sig_atomic_t;
+
+#define SIG_ERR ((void (*)(int))-1)
+#define SIG_DFL ((void (*)(int)) 0)
+#define SIG_IGN ((void (*)(int)) 1)
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGABRT 6
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGSSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+
+#define __NR_SIGNALS 23
diff --git a/include/ctype.h b/include/ctype.h
@@ -0,0 +1,45 @@
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+extern int isalnum(int c);
+extern int isalpha(int c);
+extern int islower(int c);
+extern int isupper(int c);
+extern int isdigit(int c);
+extern int isxdigit(int c);
+extern int iscntrl(int c);
+extern int isgraph(int c);
+extern int isspace(int c);
+extern int isblank(int c);
+extern int isprint(int c);
+extern int ispunct(int c);
+extern int tolower(int c);
+extern int toupper(int c);
+
+
+#define _U 0x01 /* upper */
+#define _L 0x02 /* lower */
+#define _D 0x04 /* digit */
+#define _C 0x08 /* cntrl */
+#define _P 0x10 /* punct */
+#define _S 0x20 /* white space (space/lf/tab) */
+#define _X 0x40 /* hex char */
+#define _SP 0x80 /* hard space (0x20) */
+
+extern unsigned char __ctype[];
+
+#define isalnum(c) ((__ctype+1)[c] & (_U|_L|_D))
+#define isalpha(c) ((__ctype+1)[c] & (_U|_L))
+#define iscntrl(c) ((__ctype+1)[c] & (_C))
+#define isdigit(c) ((__ctype+1)[c] & (_D))
+#define isgraph(c) ((__ctype+1)[c] & (_P|_U|_L|_D))
+#define islower(c) ((__ctype+1)[c] & (_L))
+#define isprint(c) ((__ctype+1)[c] & (_P|_U|_L|_D|_SP))
+#define ispunct(c) ((__ctype+1)[c] & (_P))
+#define isspace(c) ((__ctype+1)[c] & (_S))
+#define isupper(c) ((__ctype+1)[c] & (_U))
+#define isxdigit(c) ((__ctype+1)[c] & (_D|_X))
+
+#define isascii(c) ((unsigned)(c)<=0x7f)
+
+#endif
diff --git a/include/errno.h b/include/errno.h
@@ -0,0 +1,10 @@
+#ifndef _ERRNO_H
+#define _ERRNO_H
+
+#include <sys/errno.h>
+
+extern int errno;
+extern char *_sys_errlist[];
+extern int _sys_nerr;
+
+#endif
diff --git a/include/limits.h b/include/limits.h
@@ -0,0 +1,9 @@
+#ifndef _LIMITS_H
+#define _LIMITS_H
+
+#include <arch/limits.h>
+
+#define CHAR_BIT 8
+#define MB_LEN_MAX 1
+
+#endif
diff --git a/include/rcode.h b/include/rcode.h
@@ -0,0 +1,51 @@
+#include <stdint.h>
+#include <setjmp.h>
+
+#ifndef NDEBUG
+#define dbg printk
+#else
+#define dbg(fmt, ...)
+#endif
+
+#define PAGESIZE 4096
+
+typedef uint64_t lock_t;
+typedef struct context Ctx;
+typedef struct rscb Rscb;
+
+struct bssmap {
+ char in_panic;
+};
+
+struct rowidx {
+ unsigned char off;
+ unsigned char cnt;
+};
+
+#ifdef setjmp
+struct context {
+ unsigned char imm1, imm2;
+ jmp_buf recover;
+ int error;
+};
+#endif
+
+static inline struct bssmap *
+bss(void)
+{
+ uintptr_t addr;
+
+ addr = ((uintptr_t)&addr & ~(PAGESIZE-1));
+ return (struct bssmap *)addr;
+}
+#define bss bss()
+
+extern void rmc(unsigned imm1, unsigned imm2, Ctx *ctx);
+extern void lock(lock_t *lck);
+extern void unlock(lock_t *lck);
+
+extern const struct rowidx rowidx[];
+extern void (*const handler[])(void);
+
+extern void printk(const char * restrict fmt, ...);
+extern void panic(const char *msg);
diff --git a/include/setjmp.h b/include/setjmp.h
@@ -0,0 +1,11 @@
+#ifndef _SETJMP_H
+#define _SETJMP_H
+
+#include <arch/setjmp.h>
+
+extern int setjmp(jmp_buf env);
+extern void longjmp(jmp_buf env, int val);
+
+#define setjmp setjmp
+
+#endif
diff --git a/include/stdarg.h b/include/stdarg.h
@@ -0,0 +1,10 @@
+#ifndef _STDARG_H
+#define _STDARG_H
+
+typedef __builtin_va_list va_list;
+#define va_start(ap, last) __builtin_va_start(ap, last)
+#define va_end(ap) __builtin_va_end(ap)
+#define va_copy(to, from) __builtin_va_copy(to, from)
+#define va_arg(to, type) __builtin_va_arg(to, type)
+
+#endif
diff --git a/include/stdbool.h b/include/stdbool.h
@@ -0,0 +1,9 @@
+#ifndef _STDBOOL_H
+#define _STDBOOL_H
+
+#define bool _Bool
+#define true 1
+#define false 0
+#define __bool_true_false_are_defined 1
+
+#endif
diff --git a/include/stddef.h b/include/stddef.h
@@ -0,0 +1,12 @@
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+#include <arch/stddef.h>
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#define offsetof(st, m) ((size_t)&(((st *)0)->m))
+
+#endif
diff --git a/include/stdint.h b/include/stdint.h
@@ -0,0 +1,6 @@
+#ifndef _STDINT_H_
+#define _STDINT_H_
+
+#include <arch/stdint.h>
+
+#endif
diff --git a/include/stdio.h b/include/stdio.h
@@ -0,0 +1,123 @@
+#ifndef _STDIO_H
+#define _STDIO_H
+
+#include <arch/stdio.h>
+
+#ifndef FOPEN_MAX
+#define FOPEN_MAX 12
+#endif
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#define EOF -1
+#define SEEK_CUR 0
+#define SEEK_END 1
+#define SEEK_SET 2
+
+
+#define _IOWRITE (1 << 0)
+#define _IOREAD (1 << 1)
+#define _IORW (1 << 2)
+#define _IOEOF (1 << 3)
+#define _IOERR (1 << 4)
+#define _IOSTRG (1 << 5)
+#define _IOTXT (1 << 6)
+#define _IOFBF (1 << 7)
+#define _IOLBF (1 << 8)
+#define _IONBF (1 << 9)
+#define _IOALLOC (1 <<10)
+
+typedef struct {
+ int fd; /* file descriptor */
+ unsigned char *buf; /* pointer to i/o buffer */
+ unsigned char *rp; /* read pointer */
+ unsigned char *wp; /* write pointer */
+ unsigned char *lp; /* write pointer used when line-buffering */
+ size_t len; /* actual length of buffer */
+ unsigned short flags;
+ unsigned char unbuf[1]; /* tiny buffer for unbuffered io */
+} FILE;
+
+extern FILE __iob[FOPEN_MAX];
+
+#define stdin (&__iob[0])
+#define stdout (&__iob[1])
+#define stderr (&__iob[2])
+
+extern int remove(const char *filename);
+extern int rename(const char *old, const char *new);
+extern FILE *tmpfile(void);
+extern char *tmpnam(char *s);
+extern int fclose(FILE *fp);
+extern int fflush(FILE *fp);
+extern FILE *fopen(const char * restrict fname, const char * restrict mode);
+extern FILE *freopen(const char * restrict fname, const char * restrict mode,
+ FILE * restrict fp);
+extern void setbuf(FILE * restrict fp, char * restrict buf);
+extern int setvbuf(FILE * restrict fp,
+ char * restrict buf, int mode, size_t size);
+extern int fprintf(FILE * restrict fp, const char * restrict fmt, ...);
+extern int fscanf(FILE * restrict fp, const char * restrict fmt, ...);
+extern int printf(const char * restrict fmt, ...);
+extern int scanf(const char * restrict fmt, ...);
+extern int snprintf(char * restrict s,
+ size_t n, const char * restrict fmt, ...);
+extern int sprintf(char * restrict s, const char * restrict fmt, ...);
+extern int sscanf(const char * restrict s, const char * restrict fmt, ...);
+
+#ifdef _STDARG_H
+extern int vfprintf(FILE * restrict fp,
+ const char * restrict fmt, va_list arg);
+extern int vfscanf(FILE * restrict fp,
+ const char * restrict fmt, va_list arg);
+extern int vprintf(const char * restrict fmt, va_list arg);
+extern int vscanf(const char * restrict fmt, va_list arg);
+extern int vsnprintf(char * restrict s, size_t n, const char * restrict fmt,
+ va_list arg);
+extern int vsprintf(char * restrict s,
+ const char * restrict fmt, va_list arg);
+extern int vsscanf(const char * restrict s,
+ const char * restrict fmt, va_list arg);
+#endif
+
+extern int fgetc(FILE *fp);
+extern char *fgets(char * restrict s, int n, FILE * restrict fp);
+extern int fputc(int c, FILE *fp);
+extern int fputs(const char * restrict s, FILE * restrict fp);
+extern int getc(FILE *fp);
+extern int getchar(void);
+extern char *gets(char *s);
+extern int putc(int c, FILE *fp);
+extern int putchar(int c);
+extern int puts(const char *s);
+extern int ungetc(int c, FILE *fp);
+extern size_t fread(void * restrict ptr, size_t size, size_t nmemb,
+ FILE * restrict fp);
+extern size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb,
+ FILE * restrict fp);
+extern int fgetpos(FILE * restrict fp, fpos_t * restrict pos);
+extern int fseek(FILE *fp, long int offset, int whence);
+extern int fsetpos(FILE *fp, const fpos_t *pos);
+extern long int ftell(FILE *fp);
+extern void rewind(FILE *fp);
+extern void clearerr(FILE *fp);
+extern int feof(FILE *fp);
+extern int ferror(FILE *fp);
+extern void perror(const char *s);
+
+extern int __getc(FILE *fp);
+extern int __putc(int, FILE *fp);
+
+#define getc(fp) ((fp)->rp >= (fp)->wp ? __getc(fp) : *(fp)->rp++)
+#define putc(c, fp) ((fp)->wp >= (fp)->rp ? __putc(c,fp) : (*(fp)->wp++ = c))
+
+#define ferror(fp) ((fp)->flags & _IOERR)
+#define feof(fp) ((fp)->flags & _IOEOF)
+#define clearerr(fp) (void) ((fp)->flags &= ~(_IOERR|_IOEOF))
+#define getchar() getc(stdin)
+#define putchar(c) putc((c), stdout)
+#define setbuf(fp, b) (void) setvbuf(fp, b, b ? _IOFBF:_IONBF, BUFSIZ)
+
+#endif
diff --git a/include/stdlib.h b/include/stdlib.h
@@ -0,0 +1,64 @@
+#ifndef _STDLIB_H
+#define _STDLIB_H
+
+#include <arch/stdlib.h>
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#define _ATEXIT_MAX 32
+
+#define MB_CUR_MAX 1
+#define RAND_MAX 32767
+
+typedef struct {
+ int quot, rem;
+} div_t;
+
+typedef struct {
+ long quot, rem;
+} ldiv_t;
+
+typedef struct {
+ long long quot, rem;
+} lldiv_t;
+
+extern double atof(const char *nptr);
+extern int atoi(const char *nptr);
+extern long int atol(const char *nptr);
+extern long long int atoll(const char *nptr);
+extern double strtod(const char * restrict nptr, char ** restrict endptr);
+extern float strtof(const char * restrict nptr, char ** restrict endptr);
+extern long double strtold(const char * restrict nptr, char ** restrict endptr);
+extern long int strtol(const char * restrict nptr, char ** restrict endptr, int base);
+extern long long int strtoll(const char * restrict nptr, char ** restrict endptr,
+ int base);
+extern unsigned long int strtoul(const char * restrict nptr, char ** restrict endptr,
+ int base);
+extern unsigned long long int strtoull(const char * restrict nptr,
+ char ** restrict endptr, int base);
+extern int rand(void);
+extern void srand(unsigned int seed);
+extern void *calloc(size_t nmemb, size_t size);
+extern void free(void *ptr);
+extern void *malloc(size_t size);
+extern void *realloc(void *ptr, size_t size);
+extern void abort(void);
+extern int atexit(void (*func)(void));
+extern void exit(int status);
+extern void _Exit(int status);
+extern char *getenv(const char *name);
+extern int system(const char *string);
+extern void *bsearch(const void *key, const void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *));
+extern void qsort(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *));
+extern int abs(int j);
+extern long int labs(long int j);
+extern long long int llabs(long long int j);
+extern div_t div(int numer, int denom);
+extern ldiv_t ldiv(long int numer, long int denom);
+extern lldiv_t lldiv(long long int numer, long long int denom);
+
+#endif
diff --git a/include/string.h b/include/string.h
@@ -0,0 +1,34 @@
+#ifndef _STRING_H
+#define _STRING_H
+
+#include <arch/string.h>
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+extern void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
+extern void *memmove(void *s1, const void *s2, size_t n);
+extern char *strcpy(char * restrict s1, const char * restrict s2);
+extern char *strncpy(char * restrict s1, const char * restrict s2, size_t n);
+extern char *strcat(char * restrict s1, const char * restrict s2);
+extern char *strncat(char * restrict s1, const char * restrict s2, size_t n);
+extern int memcmp(const void *s1, const void *s2, size_t n);
+extern int strcmp(const char *s1, const char *s2);
+extern int strcoll(const char *s1, const char *s2);
+extern int strncmp(const char *s1, const char *s2, size_t n);
+extern size_t strxfrm(char * restrict s1, const char * restrict s2, size_t n);
+extern void *memchr(const void *s, int c, size_t n);
+extern char *strchr(const char *s, int c);
+extern size_t strcspn(const char *s1, const char *s2);
+extern char *strpbrk(const char *s1, const char *s2);
+extern char *strrchr(const char *s, int c);
+extern size_t strspn(const char *s1, const char *s2);
+extern char *strstr(const char *s1, const char *s2);
+extern char *strtok(char * restrict s1, const char * restrict s2);
+extern void *memset(void *s, int c, size_t n);
+extern char *strerror(int errnum);
+extern size_t strlen(const char *s);
+extern size_t strnlen(const char *s, size_t maxlen);
+
+#endif
diff --git a/include/types.h b/include/types.h
@@ -0,0 +1,10 @@
+#if __GNUC__ || __clang__
+#define UNPACKFMT __attribute__ ((format (scanf, 2, 3)))
+#define PACKFMT __attribute__ ((format (printf, 2, 3)))
+#else
+#define UNPACKFMT
+#define PACKFMT
+#endif
+
+extern int unpack(uint64_t buf[], const char *fmt, ...) UNPACKFMT;
+extern int pack(uint64_t buf[], const char *fmt, ...) PACKFMT;
diff --git a/scripts/gentbl.sh b/scripts/gentbl.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+in=rmu.cmd
+out=rmutbl.c
+tmp=gentbl.$$
+
+for i
+do
+ case $i in
+ -o)
+ out=$2
+ shift 2
+ ;;
+ -i)
+ in=$2
+ shift 2
+ ;;
+ --)
+ shift
+ ;;
+ -*)
+ echo i=$i
+ echo usage: gentbl.sh [-o file] >&2
+ exit 1
+ ;;
+ esac
+done
+
+trap "rm -f $tmp" 0 2 3
+
+sort -n -k1,2 < $in |
+awk '
+BEGIN {
+ print "#include <rcode.h>\n"
+};
+
+NF == 3 && $1 ~ /[0-9]*/ && $2 ~ /[0-9]*/ {
+ rowcnt[$1]++
+ gsub(/\./, "_", $3)
+ cmds[$1,$2] = $3
+ next
+}
+
+{
+ print "Invalid RMU command description" > "/dev/stderr"
+ exit -1
+}
+
+END {
+ for (cmd in cmds)
+ print "extern void " cmds[cmd] "(void);"
+ print ""
+
+ print "const struct rowidx rowidx[256] = {"
+ for (row in rowcnt) {
+ begin[row] = colcnt
+ printf "\t[%d] = {.off = %d, .cnt = %d},\n", row, colcnt, rowcnt[row]
+ colcnt += rowcnt[row]
+ }
+ print "};"
+
+ print "void (*const handler[])(void) = {"
+ for (row in rowcnt)
+ for (col = 0; col < rowcnt[row]; col++)
+ printf "\t[%d] = %s,\n", begin[row] + col, cmds[row,col]
+ print "};"
+}' > $tmp && mv $tmp rmctbl.c
diff --git a/scripts/rmu.cmd b/scripts/rmu.cmd
@@ -0,0 +1,43 @@
+0 0 RMU.System.InterfaceVersion
+0 1 RMU.System.Status
+0 2 RMU.System.Enable
+1 0 RMU.Local.Status
+1 1 RMU.Local.Load
+1 2 RMU.Local.Validate
+2 0 RMU.Crypto.Random
+3 0 RMU.Realm.Register
+3 1 RMU.Realm.Release
+4 0 RMU.Realm.InvalidateCurrent
+5 0 RMU.Realm.Invalidate
+5 1 RMU.Realm.GetParameterValue
+5 2 RMU.Realm.SetParameterValue
+5 3 RMU.Realm.GetParameterInheritance
+5 4 RMU.Realm.SetParameterInheritance
+5 5 RMU.Realm.Initialize
+5 6 RMU.Realm.Prepare
+5 7 RMU.Realm.Populate
+5 8 RMU.Realm.Activate
+5 9 RMU.Realm.Info
+5 10 RMU.Realm.ReadMemory
+5 11 RMU.Realm.WriteMemory
+5 12 RMU.Realm.SetMetadata
+5 13 RMU.Realm.GetMetadata
+5 14 RMU.Realm.CreateZeroMetadata
+6 0 RMU.Realm.SetCommandTrap
+7 0 RMU.Realm.AttestationReportSize
+7 1 RMU.Realm.AttestationReportInit
+7 2 RMU.Realm.AttestationReport
+8 0 RMU.Realm.ExtendBindingKeySeedValue
+8 1 RMU.Realm.SetBindingKeySeedLock
+8 2 RMU.Realm.DeriveBindingKey
+8 3 RMU.Realm.GetBindingKeySeedValue
+9 0 RMU.REC.Size
+9 1 RMU.REC.Register
+9 2 RMU.REC.Prepare
+9 3 RMU.REC.Release
+9 4 RMU.REC.ReadGeneralPurposeRegister
+9 5 RMU.REC.WriteGeneralPurposeRegister
+9 6 RMU.REC.ReadVectorRegister
+9 7 RMU.REC.WriteVectorRegister
+9 8 RMU.REC.ReadSystemRegister
+9 9 RMU.REC.WriteSystemRegister
diff --git a/scripts/rules.mk b/scripts/rules.mk
@@ -0,0 +1,85 @@
+CONF = arm64-none
+include $(PROJECTDIR)/config/$(CONF).mk
+
+INCDIR = $(PROJECTDIR)/include
+LIBDIR = $(PROJECTDIR)/lib
+BINDIR = $(PROJECTDIR)/bin
+ARCHDIR = $(PROJECTDIR)/arch/$(ARCH)
+SRCDIR = $(PROJECTDIR)/src
+SCRIPTDIR= $(PROJECTDIR)/scripts
+INCLUDES = -I$(INCDIR) -I$(INCDIR)/bits/$(ARCH)/ -I$(INCDIR)/bits/$(SYS)
+
+RCODE_CFLAGS = $(MORECFLAGS) \
+ $(INCLUDES) \
+ $(SYSCFLAGS) \
+ $(CFLAGS)
+
+RCODE_LDFLAGS = $(MORELDFLAGS) \
+ -L$(LIBDIR) \
+ $(SYSLDFLAGS) \
+ $(LDFLAGS)
+
+RCODE_ASFLAGS = $(MOREAFLAGS) \
+ $(SYSASFLAGS) \
+ $(ASFLAGS)
+
+CBMC_FLAGS = $(CFLAGS) --bounds-check --object-bits 16
+CBMC_PATHS = arch/$(ARCH)/*.c src/libc/arch/$(ARCH)/*.c src/*/*.c
+
+EMUCMD = $(EMU) $(EMUFLAGS)
+
+CC = $(CROSS_COMPILE)$(COMP)
+AS = $(CROSS_COMPILE)$(ASM)
+LD = $(CROSS_COMPILE)$(LINKER)
+OC = $(CROSS_COMPILE)$(OBJCOPY)
+
+.c.o:
+ $(CC) $(RCODE_CFLAGS) -o $@ -c $<
+
+FORALL= +@set -e ;\
+ pwd=$$PWD; \
+ for i in $(DIRS); \
+ do \
+ cd $$i; \
+ $(MAKE) $@; \
+ cd $$pwd; \
+ done
+
+all:
+
+FORCE:
+
+.SUFFIXES: .elf .bin .tst
+
+.c.s:
+ $(CC) $(RCODE_CFLAGS) -o $@ -S $<
+
+.elf.bin:
+ $(OC) -O binary $< $@
+
+$(BINDIR)/ramfw.bin: $(BINDIR)/ramfw.tst
+$(BINDIR)/romfw.bin: $(BINDIR)/romfw.tst
+
+.elf.tst:
+ @size $< | \
+ awk 'NR == 2 {\
+ if ($$2 != 0 || $$3 != 0) {\
+ printf("image %s with data section!\n",\
+ "$<") > "/dev/stderr";\
+ exit 1;\
+ }\
+ }'
+ touch $@
+
+cbmc: all FORCE
+ cbmc $(INCLUDES) $(CBMC_FLAGS) $(CBMC_PATHS)
+
+run_test: run FORCE
+ EMUCMD='$(EMUCMD)' SCRIPTDIR=$(SCRIPTDIR) ./test.sh
+
+clean: clean-files
+
+clean-files:
+ rm -f *.d *.o *.a $(TARGET)
+
+-include *.d
diff --git a/src/Makefile b/src/Makefile
@@ -0,0 +1,16 @@
+PROJECTDIR=..
+include $(PROJECTDIR)/scripts/rules.mk
+
+LIBS = libc librmu libtypes
+IMGS = ramfw romfw
+DIRS = $(LIBS) $(IMGS)
+
+all: $(IMGS) rmc.o
+
+$(IMGS): $(LIBS)
+
+$(DIRS): FORCE
+ +@cd $@ && $(MAKE)
+
+clean:
+ $(FORALL)
diff --git a/src/libc/Makefile b/src/libc/Makefile
@@ -0,0 +1,68 @@
+PROJECTDIR =../..
+LIBCARCH = arch/$(ARCH)
+include $(PROJECTDIR)/scripts/rules.mk
+
+MORECFLAGS = -I.
+
+OBJS = abort.o \
+ __assert.o \
+ memchr.o \
+ memcmp.o \
+ memcpy.o \
+ memmove.o \
+ memset.o \
+ printk.o \
+ __putc.o \
+ ctype.o \
+ isalnum.o \
+ isalpha.o \
+ isascii.o \
+ isblank.o \
+ iscntrl.o \
+ isdigit.o \
+ isgraph.o \
+ islower.o \
+ isprint.o \
+ ispunct.o \
+ isspace.o \
+ isupper.o \
+ isxdigit.o \
+ printf.o \
+ putc.o \
+ snprintf.o \
+ sprintf.o \
+ stdio.o \
+ vfprintf.o \
+ vsnprintf.o \
+ vsprintf.o \
+ toupper.o \
+ strnlen.o \
+ ferror.o \
+ _flsbuf.o \
+ errno.o \
+ atexit.o \
+ exit.o \
+ fputc.o \
+ fputs.o \
+ fprintf.o \
+ putchar.o \
+ puts.o \
+ rand.o \
+ raise.o \
+ $(LIBCARCH)/setjmp.o \
+ $(LIBCARCH)/longjmp.o \
+ $(LIBCARCH)/_Exit-$(SYS).o \
+ $(LIBCARCH)/_write-$(SYS).o \
+ $(LIBCARCH)/_getpid-$(SYS).o \
+ $(LIBCARCH)/_kill-$(SYS).o
+
+TARGET = $(PROJECTDIR)/lib/libc.a
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $?
+ ranlib $@
+
+clean:
+ rm -f arch/*/*.o arch/*/*.d
diff --git a/src/libc/__assert.c b/src/libc/__assert.c
@@ -0,0 +1,10 @@
+#include <assert.h>
+#include <stdlib.h>
+
+extern void printk(const char * restrict fmt, ...);
+
+void __assert(char *exp, char *file, long line)
+{
+ printk("%s:%ld: assertion failed '%s'\n", file, line, exp);
+ abort();
+}
diff --git a/src/libc/__putc.c b/src/libc/__putc.c
@@ -0,0 +1,76 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int _flsbuf(FILE *fp);
+
+int
+fflush(FILE *fp)
+{
+ int err;
+
+ if (fp)
+ return _flsbuf(fp);
+
+ err = 0;
+ for (fp = __iob; fp < &__iob[FOPEN_MAX]; ++fp) {
+ if ((fp->flags & _IOWRITE) == 0 && _flsbuf(fp))
+ err = EOF;
+ }
+ return err;
+}
+
+static void
+cleanup(void)
+{
+ fflush(NULL);
+}
+
+int
+__putc(int ch, FILE *fp)
+{
+ static int first = 1;
+
+ if (fp->flags & _IOERR)
+ return EOF;
+
+ if (fp->flags & _IOREAD) {
+ fp->flags |= _IOERR;
+ errno = EBADF;
+ return EOF;
+ }
+
+ if (fp->flags & _IOSTRG) {
+ fp->flags |= _IOERR;
+ return EOF;
+ }
+
+ if (first) {
+ if (atexit(cleanup)) {
+ fp->flags |= _IOERR;
+ errno = ENOMEM;
+ return EOF;
+ }
+ first = 0;
+ }
+
+ if (fp->flags & _IOLBF) {
+ if (fp->lp == fp->rp && _flsbuf(fp))
+ return EOF;
+ *fp->lp++ = ch;
+ if (ch == '\n' && _flsbuf(fp))
+ return EOF;
+ } else if (fp->flags & _IOFBF) {
+ if (fp->wp == fp->rp && _flsbuf(fp))
+ return EOF;
+ *fp->wp++ = ch;
+ } else {
+ *fp->wp++ = ch;
+ if (_flsbuf(fp))
+ return EOF;
+ }
+
+done:
+ fp->flags |= _IOWRITE;
+ return ch & 0xFF;
+}
diff --git a/src/libc/_flsbuf.c b/src/libc/_flsbuf.c
@@ -0,0 +1,22 @@
+#include <errno.h>
+#include <stdio.h>
+#include "syscall.h"
+
+int
+_flsbuf(FILE *fp)
+{
+ int lnbuf = fp->flags & _IOLBF;
+ unsigned char *p;
+ size_t cnt;
+
+ p = (lnbuf) ? fp->lp : fp->wp;
+ cnt = p - fp->buf;
+
+ if (_write(fp->fd, fp->buf, cnt) != cnt) {
+ fp->flags |= _IOERR;
+ return EOF;
+ }
+ fp->lp = fp->rp = fp->wp = fp->buf;
+
+ return 0;
+}
diff --git a/src/libc/abort.c b/src/libc/abort.c
@@ -0,0 +1,10 @@
+#include <signal.h>
+#include <stdlib.h>
+#undef abort
+
+void
+abort(void)
+{
+ raise(SIGABRT);
+ _Exit(127);
+}
diff --git a/src/libc/arch/amd64/_Exit-bsd.s b/src/libc/arch/amd64/_Exit-bsd.s
@@ -0,0 +1,8 @@
+ .file "_Exit-bsd.s"
+
+ .text
+ .globl _Exit
+_Exit:
+ movq $1,%rax
+ syscall
+ ret
diff --git a/src/libc/arch/amd64/_Exit-linux.s b/src/libc/arch/amd64/_Exit-linux.s
@@ -0,0 +1,8 @@
+ .file "_Exit-linux.s"
+
+ .text
+ .globl _Exit
+_Exit:
+ movq $60,%rax
+ syscall
+ ret
diff --git a/src/libc/arch/amd64/_getpid-bsd.s b/src/libc/arch/amd64/_getpid-bsd.s
@@ -0,0 +1,8 @@
+ .file "_getpid-bsd.s"
+
+ .text
+ .globl _getpid
+_getpid:
+ movq $20,%rax
+ syscall
+ ret
diff --git a/src/libc/arch/amd64/_getpid-linux.s b/src/libc/arch/amd64/_getpid-linux.s
@@ -0,0 +1,8 @@
+ .file "_getpid-linux.s"
+
+ .text
+ .globl _getpid
+_getpid:
+ movq $20,%rax
+ syscall
+ ret
diff --git a/src/libc/arch/amd64/_kill-bsd.s b/src/libc/arch/amd64/_kill-bsd.s
@@ -0,0 +1,8 @@
+ .file "_kill-bsd.s"
+
+ .text
+ .globl _kill
+_kill:
+ movq $37,%rax
+ syscall
+ ret
diff --git a/src/libc/arch/amd64/_kill-linux.s b/src/libc/arch/amd64/_kill-linux.s
@@ -0,0 +1,8 @@
+ .file "_kill-linux.s"
+
+ .text
+ .globl _kill
+_kill:
+ movq $37,%rax
+ syscall
+ ret
diff --git a/src/libc/arch/amd64/_write-bsd.s b/src/libc/arch/amd64/_write-bsd.s
@@ -0,0 +1,8 @@
+ .file "_write-bsd.s"
+
+ .text
+ .globl _write
+_write:
+ movq $4,%rax
+ syscall
+ ret
diff --git a/src/libc/arch/amd64/_write-linux.s b/src/libc/arch/amd64/_write-linux.s
@@ -0,0 +1,8 @@
+ .file "_write-linux.s"
+
+ .text
+ .globl _write
+_write:
+ movq $1,%rax
+ syscall
+ ret
diff --git a/src/libc/arch/amd64/longjmp.s b/src/libc/arch/amd64/longjmp.s
@@ -0,0 +1,20 @@
+ .file "longjmp"
+
+ .text
+ .globl longjmp
+longjmp:
+ mov %rsi,%rax
+ test %rax,%rax
+ jnz 1f
+ inc %rax
+1:
+ mov (%rdi),%rbx
+ mov 8(%rdi),%rbp
+ mov 16(%rdi),%r12
+ mov 24(%rdi),%r13
+ mov 32(%rdi),%r14
+ mov 40(%rdi),%r15
+ mov 48(%rdi),%rdx
+ mov %rdx,%rsp
+ mov 56(%rdi),%rdx
+ jmp *%rdx
diff --git a/src/libc/arch/amd64/setjmp.s b/src/libc/arch/amd64/setjmp.s
@@ -0,0 +1,17 @@
+ .file "setjmp.s"
+
+ .text
+ .globl setjmp
+setjmp:
+ mov %rbx,(%rdi)
+ mov %rbp,8(%rdi)
+ mov %r12,16(%rdi)
+ mov %r13,24(%rdi)
+ mov %r14,32(%rdi)
+ mov %r15,40(%rdi)
+ lea 8(%rsp),%rdx
+ mov %rdx,48(%rdi)
+ mov (%rsp),%rdx
+ mov %rdx,56(%rdi)
+ xor %rax,%rax
+ ret
diff --git a/src/libc/arch/arm64/_Exit-linux.s b/src/libc/arch/arm64/_Exit-linux.s
@@ -0,0 +1,8 @@
+ .file "_Exit-linux.s"
+
+ .text
+ .globl _Exit
+_Exit:
+ mov x8,#93
+ svc 0
+ ret
diff --git a/src/libc/arch/arm64/_Exit-none.s b/src/libc/arch/arm64/_Exit-none.s
@@ -0,0 +1,9 @@
+ .file "_Exit-none.s"
+
+ .text
+ .globl _Exit,panic
+_Exit:
+ ldr x0,=msg
+ b panic
+
+msg: .asciz "_Exit"
diff --git a/src/libc/arch/arm64/_getpid-linux.s b/src/libc/arch/arm64/_getpid-linux.s
@@ -0,0 +1,8 @@
+ .file "_getpid-linux.s"
+
+ .text
+ .globl _getpid
+_getpid:
+ mov x8,#172
+ svc 0
+ ret
diff --git a/src/libc/arch/arm64/_getpid-none.s b/src/libc/arch/arm64/_getpid-none.s
@@ -0,0 +1,9 @@
+ .file "_getpid-none.s"
+
+ .text
+ .globl _getpid
+_getpid:
+ ldr x0,=msg
+ b panic
+
+msg: .asciz "_getpid"
diff --git a/src/libc/arch/arm64/_kill-linux.s b/src/libc/arch/arm64/_kill-linux.s
@@ -0,0 +1,8 @@
+ .file "_kill-linux.s"
+
+ .text
+ .globl _kill
+_kill:
+ mov x8,#129
+ svc 0
+ ret
diff --git a/src/libc/arch/arm64/_kill-none.s b/src/libc/arch/arm64/_kill-none.s
@@ -0,0 +1,9 @@
+ .file "_kill-none.s"
+
+ .text
+ .globl _kill,panic
+_kill:
+ ldr x0,=msg
+ b panic
+
+msg: .asciz "_kill"
diff --git a/src/libc/arch/arm64/_write-linux.s b/src/libc/arch/arm64/_write-linux.s
@@ -0,0 +1,8 @@
+ .file "_write-linux.s"
+
+ .text
+ .globl _write
+_write:
+ mov x8,#64
+ svc 0
+ ret
diff --git a/src/libc/arch/arm64/_write-none.s b/src/libc/arch/arm64/_write-none.s
@@ -0,0 +1,80 @@
+ .file "_write-none.s"
+
+BASE = 0x1c090000
+CLK = 24000000
+BAUD = 115200
+
+CR = 0x30
+LCR_H = 0x2c
+FBRD = 0x28
+IBRD = 0x24
+FR = 0x18
+ECR = 0x04
+DR = 0x0
+
+CR_RXE = (1<<9)
+CR_TXE = (1<<8)
+CR_EN = (1<<0)
+
+LCR_H_FEN = (1<<4)
+LCR_H_WLEN_8 = (3<<5)
+
+FR_TXFF_BIT = 5
+FR_BUSY_BIT = 3
+
+ .text
+ .globl _uart_init,_write
+
+_uart_init:
+ ldr x0,=BASE
+ ldr x1,=CLK
+ ldr x2,=BAUD
+
+ ldr w3,[x0,CR]
+ mov w4,CR_EN
+ bic w3, w3, w4
+ str w3,[x0,CR]
+ lsl w1,w1,2
+ udiv w2,w1,w2
+ lsr w1,w2,6
+ str w1,[x0,IBRD]
+ and w1,w2,0x3f
+ str w1,[x0,FBRD]
+ mov w1,LCR_H_FEN|LCR_H_WLEN_8
+ str w1,[x0,LCR_H]
+ str wzr,[x0,ECR]
+ mov w1,CR_RXE|CR_TXE|CR_EN
+ str w1,[x0,CR]
+
+ adr x1,ansism
+ mov x2,5
+ b _write
+
+/*
+ * x0 = fd (unused)
+ * x1 = buf
+ * x2 = cnt
+ */
+_write: ldr x3,=BASE
+
+noready:
+ ldr w4,[x3,FR]
+ tbnz w4,FR_TXFF_BIT,noready
+
+ ldrb w4,[x1],#1
+ str w4,[x3,DR]
+ subs x2,x2,#1
+ cbnz x2,noready
+
+ mov w5,'\n'
+ cmp w4,w0
+ b.eq busy
+ ret
+
+busy:
+ ldr w2,[x3,FR]
+ tbnz w2,FR_BUSY_BIT,busy
+ ret
+
+ansism: .byte 0x1b
+ .ascii "[20h"
diff --git a/src/libc/arch/arm64/longjmp.s b/src/libc/arch/arm64/longjmp.s
@@ -0,0 +1,22 @@
+ .file "longjmp.s"
+
+ .text
+ .globl longjmp
+longjmp:
+ ldp x19, x20, [x0,#0]
+ ldp x21, x22, [x0,#16]
+ ldp x23, x24, [x0,#32]
+ ldp x25, x26, [x0,#48]
+ ldp x27, x28, [x0,#64]
+ ldp x29, x30, [x0,#80]
+ ldr x2, [x0,#104]
+ mov sp, x2
+ ldp d8 , d9, [x0,#112]
+ ldp d10, d11, [x0,#128]
+ ldp d12, d13, [x0,#144]
+ ldp d14, d15, [x0,#160]
+
+ mov x0, x1
+ cbnz x1, 1f
+ mov x0, #1
+1: br x30
diff --git a/src/libc/arch/arm64/raise.c b/src/libc/arch/arm64/raise.c
@@ -0,0 +1,9 @@
+#include "signal.h"
+
+#undef raise
+
+int
+raise(int signum)
+{
+ panic("aborted");
+}
diff --git a/src/libc/arch/arm64/setjmp.s b/src/libc/arch/arm64/setjmp.s
@@ -0,0 +1,20 @@
+ .file "setjmp.s"
+
+ .text
+ .globl setjmp
+setjmp:
+ // IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers
+ stp x19, x20, [x0,#0]
+ stp x21, x22, [x0,#16]
+ stp x23, x24, [x0,#32]
+ stp x25, x26, [x0,#48]
+ stp x27, x28, [x0,#64]
+ stp x29, x30, [x0,#80]
+ mov x2, sp
+ str x2, [x0,#104]
+ stp d8, d9, [x0,#112]
+ stp d10, d11, [x0,#128]
+ stp d12, d13, [x0,#144]
+ stp d14, d15, [x0,#160]
+ mov x0, #0
+ ret
diff --git a/src/libc/atexit.c b/src/libc/atexit.c
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+#include <errno.h>
+#undef atexit
+
+extern void (*_exitf[_ATEXIT_MAX])(void);
+extern unsigned _exitn;
+
+int
+atexit(void (*fun)(void))
+{
+ if (_exitn == _ATEXIT_MAX) {
+ errno = ENOMEM;
+ return -1;
+ }
+ _exitf[_exitn++] = fun;
+ return 0;
+}
diff --git a/src/libc/ctype.c b/src/libc/ctype.c
@@ -0,0 +1,24 @@
+#include <ctype.h>
+
+int __ctmp;
+
+/* __ctype is shifted by one to match EOF */
+unsigned char __ctype[257] = {
+ 0, /* EOF */
+ _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
+ _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
+ _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
+ _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
+ _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
+ _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
+ _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
+ _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
+ _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
+ _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
+ _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
+ _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
+ _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
+ _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
+ _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
+ _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
+};
diff --git a/src/libc/errno.c b/src/libc/errno.c
@@ -0,0 +1 @@
+int errno;
diff --git a/src/libc/exit.c b/src/libc/exit.c
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+#undef exit
+
+void (*_exitf[_ATEXIT_MAX])(void);
+unsigned _exitn;
+
+void
+exit(int status)
+{
+ while (_exitn > 0)
+ (*_exitf[--_exitn])();
+ _Exit(status);
+}
diff --git a/src/libc/ferror.c b/src/libc/ferror.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#undef ferror
+
+int
+ferror(FILE *fp)
+{
+ return fp->flags & _IOERR;
+}
diff --git a/src/libc/fprintf.c b/src/libc/fprintf.c
@@ -0,0 +1,15 @@
+#include <stdarg.h>
+#include <stdio.h>
+#undef fprintf
+
+int
+fprintf(FILE * restrict fp, const char * restrict fmt, ...)
+{
+ va_list va;
+ int cnt;
+
+ va_start(va, fmt);
+ cnt = vfprintf(fp, fmt, va);
+ va_end(va);
+ return cnt;
+}
diff --git a/src/libc/fputc.c b/src/libc/fputc.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#undef fputc
+
+int
+fputc(int c, FILE *fp)
+{
+ return putc(c, fp);
+}
diff --git a/src/libc/fputs.c b/src/libc/fputs.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#undef fputs
+
+int
+fputs(const char * restrict bp, FILE * restrict fp)
+{
+ int r, ch;
+
+ while (ch = *bp++)
+ r = putc(ch, fp);
+ return r;
+}
diff --git a/src/libc/isalnum.c b/src/libc/isalnum.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef isalnum
+
+int
+isalnum(int c)
+{
+ return (__ctype+1)[c] & (_U|_L|_D);
+}
diff --git a/src/libc/isalpha.c b/src/libc/isalpha.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef isalpha
+
+int
+isalpha(int c)
+{
+ return (__ctype+1)[c] & (_U|_L);
+}
diff --git a/src/libc/isascii.c b/src/libc/isascii.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef isascii
+
+int
+isascii(int c)
+{
+ return c <= 0x7f;
+}
diff --git a/src/libc/isblank.c b/src/libc/isblank.c
@@ -0,0 +1,7 @@
+#include <ctype.h>
+
+int
+isblank(int c)
+{
+ return (c == ' ') || (c == '\t');
+}
diff --git a/src/libc/iscntrl.c b/src/libc/iscntrl.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef iscntrl
+
+int
+iscntrl(int c)
+{
+ return (__ctype+1)[c] & (_C);
+}
diff --git a/src/libc/isdigit.c b/src/libc/isdigit.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef isdigit
+
+int
+isdigit(int c)
+{
+ return (__ctype+1)[c] & (_D);
+}
diff --git a/src/libc/isgraph.c b/src/libc/isgraph.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef isgraph
+
+int
+isgraph(int c)
+{
+ return (__ctype+1)[c] & (_P|_U|_L|_D);
+}
diff --git a/src/libc/islower.c b/src/libc/islower.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef islower
+
+int
+islower(int c)
+{
+ return (__ctype+1)[c] & _L;
+}
diff --git a/src/libc/isprint.c b/src/libc/isprint.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef isprint
+
+int
+isprint(int c)
+{
+ return (__ctype+1)[c] & (_P|_U|_L|_D|_SP);
+}
diff --git a/src/libc/ispunct.c b/src/libc/ispunct.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef ispunct
+
+int
+ispunct(int c)
+{
+ return (__ctype+1)[c] & (_P);
+}
diff --git a/src/libc/isspace.c b/src/libc/isspace.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef isspace
+
+int
+isspace(int c)
+{
+ return (__ctype+1)[c] & _S;
+}
diff --git a/src/libc/isupper.c b/src/libc/isupper.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef isupper
+
+int
+isupper(int c)
+{
+ return (__ctype+1)[c] & _U;
+}
diff --git a/src/libc/isxdigit.c b/src/libc/isxdigit.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef isxdigit
+
+int
+isxdigit(int c)
+{
+ return (__ctype+1)[c] & (_D|_X);
+}
diff --git a/src/libc/memchr.c b/src/libc/memchr.c
@@ -0,0 +1,12 @@
+#include <string.h>
+#undef memchr
+
+void *
+memchr(const void *s, int c, size_t n)
+{
+ unsigned char *bp = (unsigned char *) s;
+
+ while (n > 0 && *bp++ != c)
+ --n;
+ return (n == 0) ? NULL : bp-1;
+}
diff --git a/src/libc/memcmp.c b/src/libc/memcmp.c
@@ -0,0 +1,14 @@
+#include <string.h>
+#undef memcmp
+
+int
+memcmp(const void *s1, const void *s2, size_t n)
+{
+ const char *s = s1;
+ const char *t = s2;
+
+ for ( ; n > 0 && *s == *t; --n)
+ ++s, ++t;
+
+ return (n > 0) ? *(unsigned char *) s - *(unsigned char *) t : 0;
+}
diff --git a/src/libc/memcpy.c b/src/libc/memcpy.c
@@ -0,0 +1,13 @@
+#include <string.h>
+#undef memcpy
+
+void *
+memcpy(void * restrict dst, const void * restrict src, size_t n)
+{
+ char *s1 = dst;
+ const char *s2 = src;
+
+ while (n-- > 0)
+ *s1++ = *s2++;
+ return dst;
+}
diff --git a/src/libc/memmove.c b/src/libc/memmove.c
@@ -0,0 +1,18 @@
+#include <string.h>
+#undef memmove
+
+void *
+memmove(void *dst, const void *src, size_t n)
+{
+ char *d = dst, *s = (char *) src;
+
+ if (d < s) {
+ while (n-- > 0)
+ *d++ = *s++;
+ } else {
+ s += n-1, d += n-1;
+ while (n-- > 0)
+ *d-- = *s--;
+ }
+ return dst;
+}
diff --git a/src/libc/memset.c b/src/libc/memset.c
@@ -0,0 +1,12 @@
+#include <string.h>
+#undef memset
+
+void *
+memset(void *s, int c, size_t n)
+{
+ char *m = s;
+
+ while (n-- > 0)
+ *m++ = c;
+ return s;
+}
diff --git a/src/libc/printf.c b/src/libc/printf.c
@@ -0,0 +1,15 @@
+#include <stdarg.h>
+#include <stdio.h>
+#undef printf
+
+int
+printf(const char * restrict fmt, ...)
+{
+ int cnt;
+ va_list va;
+
+ va_start(va, fmt);
+ cnt = vfprintf(stdout, fmt, va);
+ va_end(va);
+ return cnt;
+}
diff --git a/src/libc/printk.c b/src/libc/printk.c
@@ -0,0 +1,117 @@
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "syscall.h"
+
+static void
+putch(int c)
+{
+ _write(1, &c, 1);
+}
+
+static void
+printn(long long n, int base, int sign)
+{
+ int first, d;
+ unsigned long long div;
+ const static char digits[] = "0123456789ABCDEF";
+
+ switch (base) {
+ case 8:
+ div = 01000000000000000000000u;
+ break;
+ case 10:
+ div = 10000000000000000000u;
+ break;
+ case 16:
+ div = 0x1000000000000000u;
+ break;
+ }
+
+ if (sign && n < 0) {
+ n = -n;
+ putch('-');
+ }
+
+ for (first = 1; div > 0; div /= base) {
+ d = n / div;
+ if (d == 0 && first && div != 1)
+ continue;
+ n -= d * div;
+ putch(digits[d]);
+ first = 0;
+ }
+}
+
+static long long
+getnum(va_list *va, int size)
+{
+ switch (size) {
+ case 0:
+ return va_arg(*va, int);
+ case 1:
+ return va_arg(*va, long);
+ case 2:
+ return va_arg(*va, long long);
+ case 3:
+ default:
+ return (long long) va_arg(*va, void *);
+ }
+}
+
+void
+printk(const char * restrict fmt, ...)
+{
+ char c;
+ va_list va;
+ int base, sign, size;
+ char *s;
+
+ va_start(va, fmt);
+ while (( c = *fmt++) != '\0') {
+ if (c != '%') {
+ putch(c);
+ continue;
+ }
+
+ sign = 0;
+ size = 0;
+flags:
+ switch (c = *fmt++) {
+ case 'l':
+ size++;
+ goto flags;
+ case 'o':
+ base = 8;
+ goto print_number;
+ case 'd':
+ sign = 1;
+ case 'u':
+ base = 10;
+ goto print_number;
+ case 'p':
+ size = 3;
+ case 'X':
+ case 'x':
+ base = 16;
+ print_number:
+ printn(getnum(&va, size), base, sign);
+ break;
+ case 's':
+ for (s = va_arg(va, char *); *s; s++)
+ putch(*s);
+ break;
+ case 'c':
+ c = va_arg(va, int);
+ case '%':
+ putch(c);
+ break;
+ case '\0':
+ goto out_loop;
+ }
+ }
+
+out_loop:
+ va_end(va);
+}
diff --git a/src/libc/putc.c b/src/libc/putc.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#undef putc
+
+int
+putc(int ch, FILE *fp)
+{
+ return (fp->wp >= fp->rp) ? __putc(ch,fp) : (*fp->wp++ = ch);
+}
diff --git a/src/libc/putchar.c b/src/libc/putchar.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#undef putchar
+
+int
+putchar(int ch)
+{
+ return putc(ch, stdout);
+}
diff --git a/src/libc/puts.c b/src/libc/puts.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#undef puts
+
+int
+puts(const char *str)
+{
+ int ch;
+
+ while (ch = *str++)
+ putchar(ch);
+ return putchar('\n');
+}
diff --git a/src/libc/raise.c b/src/libc/raise.c
@@ -0,0 +1,14 @@
+
+#include <stddef.h>
+#include "signal.h"
+
+extern int _getpid(void);
+extern int _kill(int pid, int signum);
+
+#undef raise
+
+int
+raise(int signum)
+{
+ return _kill(_getpid(), signum);
+}
diff --git a/src/libc/rand.c b/src/libc/rand.c
@@ -0,0 +1,18 @@
+#include <stdlib.h>
+#undef rand
+#undef srand
+
+static unsigned long next;
+
+void
+srand(unsigned seed)
+{
+ next = seed;
+}
+
+int
+rand(void) /* RAND_MAX assumed to be 32767. */
+{
+ next = next * 1103515245 + 12345;
+ return (unsigned)(next/65536) % 32768;
+}
diff --git a/src/libc/signal.h b/src/libc/signal.h
@@ -0,0 +1,35 @@
+#ifndef _SIGNAL_H
+#define _SIGNAL_H
+
+typedef int sig_atomic_t;
+
+#define SIG_ERR ((void (*)(int))-1)
+#define SIG_DFL ((void (*)(int)) 0)
+#define SIG_IGN ((void (*)(int)) 1)
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGABRT 6
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGSSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+
+#define __NR_SIGNALS 23
+
+void ( *signal(int signum, void (*handler)(int)) ) (int);
+int raise(int sig);
+
+#endif
diff --git a/src/libc/snprintf.c b/src/libc/snprintf.c
@@ -0,0 +1,16 @@
+#include <stdarg.h>
+#include <stdio.h>
+#undef snprintf
+
+int
+snprintf(char * restrict s, size_t siz, const char * restrict fmt, ...)
+{
+ int r;
+ va_list va;
+
+ va_start(va, fmt);
+ r = vsnprintf(s, siz, fmt, va);
+ va_end(va);
+
+ return r;
+}
diff --git a/src/libc/sprintf.c b/src/libc/sprintf.c
@@ -0,0 +1,16 @@
+#include <stdarg.h>
+#include <stdio.h>
+#undef sprintf
+
+int
+sprintf(char * restrict s, const char * restrict fmt, ...)
+{
+ int r;
+
+ va_list va;
+ va_start(va, fmt);
+ r = vsprintf(s, fmt, va);
+ va_end(va);
+
+ return r;
+}
diff --git a/src/libc/stdio.c b/src/libc/stdio.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+
+static unsigned char inbuf[BUFSIZ];
+static unsigned char outbuf[BUFSIZ];
+
+FILE __iob[FOPEN_MAX] = {
+ {
+ .fd = 0,
+ .buf = inbuf,
+ .len = BUFSIZ,
+ .flags = _IOREAD,
+ .lp = inbuf,
+ .rp = inbuf,
+ .wp = inbuf,
+ },
+ {
+ .fd = 1,
+ .buf = outbuf,
+ .len = BUFSIZ,
+ .flags = _IOWRITE | _IOLBF,
+ .lp = outbuf,
+ .rp = outbuf,
+ .wp = outbuf,
+ },
+ {
+ .fd = 2,
+ .buf = stderr->unbuf,
+ .len = sizeof(stderr->unbuf),
+ .flags = _IOWRITE | _IONBF,
+ .rp = stderr->unbuf,
+ .wp = stderr->unbuf,
+ },
+};
diff --git a/src/libc/strcat.c b/src/libc/strcat.c
@@ -0,0 +1,14 @@
+#include <string.h>
+#undef strcat
+
+char *
+strcat(char * restrict dst, const char * restrict src)
+{
+ char *ret = dst;
+
+ while (*dst)
+ ++dst;
+ while (*dst++ = *src++)
+ ;
+ return ret;
+}
diff --git a/src/libc/strchr.c b/src/libc/strchr.c
@@ -0,0 +1,10 @@
+#include <string.h>
+#undef strchr
+
+char *
+strchr(const char *s, int c)
+{
+ while (*s && *s != c)
+ ++s;
+ return (*s == c) ? (char *)s : NULL;
+}
diff --git a/src/libc/strcmp.c b/src/libc/strcmp.c
@@ -0,0 +1,10 @@
+#include <string.h>
+#undef strcmp
+
+int
+strcmp(const char *s1, const char *s2)
+{
+ while (*s1 && *s2 && *s1 == *s2)
+ ++s1, ++s2;
+ return *(unsigned char *)s1 - *(unsigned char *)s2;
+}
diff --git a/src/libc/strcoll.c b/src/libc/strcoll.c
@@ -0,0 +1,10 @@
+#include <string.h>
+#undef strcoll
+
+int
+strcoll(const char *s1, const char *s2)
+{
+ while (*s1 && *s2 && *s1 == *s2)
+ ++s1, ++s2;
+ return *(unsigned char *) s1 - *(unsigned char *) s2;
+}
diff --git a/src/libc/strcpy.c b/src/libc/strcpy.c
@@ -0,0 +1,12 @@
+#include <string.h>
+#undef strcpy
+
+char *
+strcpy(char * restrict dst, const char * restrict src)
+{
+ char *ret = dst;
+
+ while (*dst++ = *src++)
+ ;
+ return ret;
+}
diff --git a/src/libc/strcspn.c b/src/libc/strcspn.c
@@ -0,0 +1,21 @@
+#include <string.h>
+#undef strcspn
+
+size_t
+strcspn(const char *s1, const char *s2)
+{
+ const unsigned char *s = s1;
+ const unsigned char *accept = s2;
+ unsigned ch;
+ size_t n;
+ char buf[__NUMCHARS];
+
+ memset(buf, 0, sizeof(buf));
+ while (ch = *accept++)
+ buf[ch] = 1;
+
+ for (n = 0; (ch = *s++) && !buf[ch]; ++n)
+ ;
+
+ return n;
+}
diff --git a/src/libc/strerror.c b/src/libc/strerror.c
@@ -0,0 +1,12 @@
+#include <errno.h>
+#include <string.h>
+#undef strerror
+
+char *
+strerror(int errnum)
+{
+ if (errnum < _sys_nerr)
+ return _sys_errlist[errnum];
+ else
+ return "Unknown error";
+}
diff --git a/src/libc/strftime.c b/src/libc/strftime.c
@@ -0,0 +1,246 @@
+#include <time.h>
+#include <string.h>
+#include "libc.h"
+#undef strftime
+
+static char *days[] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday",
+};
+
+static char *months[] = {
+ "January", "February", "March", "April",
+ "May", "June", "July", "August",
+ "September", "October", "November", "December"
+};
+
+static char *am_pm[] = {"AM", "PM"};
+
+static size_t
+sval(char *s, size_t siz, char **strs, int abrev, int idx, int max)
+{
+ char *str;
+ size_t len;
+
+ if (idx < 0 && idx >= max)
+ goto wrong;
+
+ str = strs[idx];
+ len = (!abrev) ? strlen(str) : 3;
+ if (len > siz)
+ goto wrong;
+
+ memcpy(s, str, len);
+ return len;
+
+wrong:
+ *s = '?';
+ return 1;
+}
+
+static size_t
+dval(char *s, size_t siz, int prec, int fill, int val)
+{
+ char *t;
+ int n;
+ static char digits[] = "0123456789";
+
+ if (prec > siz || val < 0) {
+ *s = '?';
+ return 1;
+ }
+
+ n = prec;
+ do {
+ s[--n] = digits[val % 10];
+ val /= 10;
+ } while (n > 0 && val > 0);
+
+ while (n > 0)
+ s[--n] = fill;
+
+ return prec;
+}
+
+static size_t
+timezone(char *s, size_t prec, const struct tm * restrict tm)
+{
+ long off = tm->tm_gmtoff;
+
+ if (prec < 5) {
+ *s = '?';
+ return 1;
+ }
+
+ if (off >= 0) {
+ *s++ = '+';
+ } else {
+ *s++ = '-';
+ off = -off;
+ }
+
+ dval(s, 2, 2, '0', off / 3600);
+ dval(s, 2, 2, '0', (off % 3600) / 60);
+
+ return 5;
+}
+
+size_t
+strftime(char * restrict s, size_t siz,
+ const char * restrict fmt,
+ const struct tm * restrict tm)
+{
+ int ch, abrev, val, fill, width;
+ size_t n, inc;
+ char *tfmt;
+
+ for (n = siz-1; (ch = *fmt++) && n > 0; s += inc, n -= inc) {
+ if (ch != '%') {
+ *s = ch;
+ inc = 1;
+ continue;
+ }
+
+ abrev = 0;
+ fill = '0';
+ width = 2;
+
+ switch (*fmt++) {
+ case 'Z':
+ if (!tm->tm_zone)
+ break;
+ inc = sval(s, n, &tm->tm_zone, 0, 0, 1);
+ break;
+ case 'a':
+ abrev = 1;
+ case 'A':
+ inc = sval(s, n, days, abrev, tm->tm_wday, 7);
+ break;
+ case 'h':
+ case 'b':
+ abrev = 1;
+ case 'B':
+ inc = sval(s, n, months, abrev, tm->tm_mon, 12);
+ break;
+ case 'p':
+ inc = sval(s, n, am_pm, 0, tm->tm_hour > 12, 2);
+ break;
+ case 'c':
+ tfmt = "%a %b %e %T %Y";
+ goto recursive;
+ case 'D':
+ tfmt = "%m/%d/%y";
+ goto recursive;
+ case 'F':
+ tfmt = "%Y-%m-%d";
+ goto recursive;
+ case 'R':
+ tfmt = "%H:%M";
+ goto recursive;
+ case 'X':
+ case 'T':
+ tfmt = "%H:%M:%S";
+ goto recursive;
+ case 'r':
+ tfmt = "%I:%M:%S %p";
+ goto recursive;
+ case 'x':
+ tfmt = "%m/%d/%y";
+ goto recursive;
+ recursive:
+ inc = strftime(s, n+1, tfmt, tm) - 1;
+ break;
+ case 'n':
+ val = '\n';
+ goto character;
+ case 't':
+ val = '\t';
+ goto character;
+ case '%':
+ val = '%';
+ character:
+ *s = val;
+ inc = 1;
+ break;
+ case 'e':
+ fill = ' ';
+ val = tm->tm_mday;
+ goto number;
+ case 'd':
+ val = tm->tm_mday;
+ goto number;
+ case 'V':
+ case 'g':
+ case 'G':
+ /* TODO */
+ break;
+ case 'C':
+ val = tm->tm_year / 100;
+ goto number;
+ case 'H':
+ val = tm->tm_hour;
+ goto number;
+ case 'I':
+ val = tm->tm_hour;
+ if (val == 0)
+ val = 12;
+ if (val > 12)
+ val -= 12;
+ goto number;
+ case 'j':
+ width = 3;
+ val = tm->tm_yday+1;
+ goto number;
+ case 'm':
+ val = tm->tm_mon+1;
+ goto number;
+ case 'M':
+ val = tm->tm_min;
+ goto number;
+ case 'S':
+ val = tm->tm_sec;
+ goto number;
+ case 'u':
+ width = 1;
+ val = tm->tm_wday+1;
+ goto number;
+ case 'U':
+ val = tm->tm_yday / 7;
+ if (_newyear(tm->tm_year) == SAT)
+ val++;
+ goto number;
+ case 'W':
+ val = tm->tm_yday / 7;
+ if (_newyear(tm->tm_year) == MON)
+ val++;
+ goto number;
+ case 'w':
+ width = 1;
+ val = tm->tm_wday;
+ goto number;
+ case 'y':
+ val = tm->tm_year%100;
+ goto number;
+ case 'Y':
+ width = 4;
+ val = 1900 + tm->tm_year;
+ number:
+ inc = dval(s, n, width, fill, val);
+ break;
+ case 'z':
+ inc = timezone(s, n, tm);
+ break;
+ case 'E':
+ case 'O':
+ if (*fmt != '\0')
+ fmt += 2;;
+ case '\0':
+ inc = 0;
+ --fmt;
+ break;
+ }
+ }
+ *s = '\0';
+
+ return siz - n;
+}
diff --git a/src/libc/strlen.c b/src/libc/strlen.c
@@ -0,0 +1,12 @@
+#include <string.h>
+#undef strlen
+
+size_t
+strlen(const char *s)
+{
+ const char *t;
+
+ for (t = s; *t; ++t)
+ ;
+ return t - s;
+}
diff --git a/src/libc/strncat.c b/src/libc/strncat.c
@@ -0,0 +1,15 @@
+#include <string.h>
+#undef strncat
+
+char *
+strncat(char * restrict dst, const char * restrict src, size_t n)
+{
+ char *ret = dst;
+
+ while (*dst)
+ ++dst;
+ while (n-- > 0 && *src)
+ *dst++ = *src++;
+ *dst = '\0';
+ return ret;
+}
diff --git a/src/libc/strncmp.c b/src/libc/strncmp.c
@@ -0,0 +1,14 @@
+#include <string.h>
+#undef strncmp
+
+int
+strncmp(const char *s1, const char *s2, size_t n)
+{
+ int c;
+
+ for ( ; n > 0 && (c = *s1) && c == *s2; --n)
+ ++s1, ++s2;
+ if (n == 0)
+ return 0;
+ return *(unsigned char *) s1 - *(unsigned char *) s2;
+}
diff --git a/src/libc/strncpy.c b/src/libc/strncpy.c
@@ -0,0 +1,14 @@
+#include <string.h>
+#undef strncpy
+
+char *
+strncpy(char * restrict dst, const char * restrict src, size_t n)
+{
+ char *ret = dst;
+
+ for (; n > 0 && *src; --n)
+ *dst++ = *src++;
+ while (n-- > 0)
+ *dst++ = '\0';
+ return ret;
+}
diff --git a/src/libc/strnlen.c b/src/libc/strnlen.c
@@ -0,0 +1,13 @@
+#include <string.h>
+
+#undef strnlen
+
+size_t
+strnlen(const char *s, size_t maxlen)
+{
+ size_t n;
+
+ for (n = 0; n < maxlen && *s++; ++n)
+ ;
+ return n;
+}
diff --git a/src/libc/strpbrk.c b/src/libc/strpbrk.c
@@ -0,0 +1,20 @@
+#include <string.h>
+#undef strpbrk
+
+char *
+strpbrk(const char *s1, const char *s2)
+{
+ const unsigned char *s = s1;
+ const unsigned char *accept = s2;
+ unsigned ch;
+ char buf[__NUMCHARS];
+
+ memset(buf, 0, sizeof(buf));
+ while (ch = *accept++)
+ buf[ch] = 1;
+
+ while ((ch = *s) && !buf[ch])
+ s++;
+
+ return (ch == '\0') ? NULL : (char *) s;
+}
diff --git a/src/libc/strrchr.c b/src/libc/strrchr.c
@@ -0,0 +1,14 @@
+#include <string.h>
+#undef strrchr
+
+char *
+strrchr(const char *s, int c)
+{
+ const char *t = s;
+
+ while (*t)
+ ++t;
+ while (t > s && *t != c)
+ --t;
+ return (*t == c) ? (char *)t : NULL;
+}
diff --git a/src/libc/strspn.c b/src/libc/strspn.c
@@ -0,0 +1,21 @@
+#include <string.h>
+#undef strspn
+
+size_t
+strspn(const char *s1, const char *s2)
+{
+ const unsigned char *s = s1;
+ const unsigned char *accept = s2;
+ unsigned ch;
+ size_t n;
+ char buf[__NUMCHARS];
+
+ memset(buf, 0, sizeof(buf));
+ while (ch = *accept++)
+ buf[ch] = 1;
+
+ for (n = 0; (ch = *s++) && buf[ch]; ++n)
+ ;
+
+ return n;
+}
diff --git a/src/libc/strstr.c b/src/libc/strstr.c
@@ -0,0 +1,18 @@
+#include <stddef.h>
+#include <string.h>
+#undef strstr
+
+char *
+strstr(const char *s1, const char *s2)
+{
+ const char *p;
+ int c = *s2;
+
+ if (c == '\0')
+ return NULL;
+ for (p = s1; p = strchr(p, c); ++p) {
+ if (!strcmp(p, s2))
+ return (char *) p;
+ }
+ return NULL;
+}
diff --git a/src/libc/strtok.c b/src/libc/strtok.c
@@ -0,0 +1,25 @@
+#include <string.h>
+#undef strtok
+
+char *
+strtok(char * restrict s, const char * restrict delim)
+{
+ static char *line;
+
+ if (s)
+ line = s;
+ if (!s && !line)
+ return NULL;
+
+ s = line + strspn(line, delim);
+ if (*s == '\0')
+ return line = NULL;
+
+ line = s + strcspn(s, delim);
+ if (*line != '\0')
+ *line++ = '\0';
+ else
+ line = NULL;
+
+ return s;
+}
diff --git a/src/libc/strxfrm.c b/src/libc/strxfrm.c
@@ -0,0 +1,12 @@
+#include <string.h>
+#undef strxfrm
+
+size_t
+strxfrm(char * restrict dst, const char * restrict src, size_t n)
+{
+ size_t len = strlen(src);
+
+ if (len < n)
+ strcpy(dst, src);
+ return len;
+}
diff --git a/src/libc/syscall.h b/src/libc/syscall.h
@@ -0,0 +1,8 @@
+extern void *_brk(void *addr);
+extern int _open(const char *path, int flags);
+extern int _close(int fd);
+extern int _read(int fd, void *buf, size_t n);
+extern int _write(int fd, void *buf, size_t n);
+extern int _lseek(int fd, long off, int whence);
+extern void _Exit(int status);
+extern int _access(char *path, int mode);
diff --git a/src/libc/toupper.c b/src/libc/toupper.c
@@ -0,0 +1,8 @@
+#include <ctype.h>
+#undef toupper
+
+int
+toupper(int c)
+{
+ return (islower(c)) ? c & ~0x20 : c;
+}
diff --git a/src/libc/vfprintf.c b/src/libc/vfprintf.c
@@ -0,0 +1,311 @@
+#include <ctype.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#undef vfprintf
+
+enum {
+ LONG = 1 << 0,
+ LLONG = 1 << 1,
+ SHORT = 1 << 2,
+ CHAR = 1 << 3,
+ SIZET = 1 << 4,
+ PTRDIFF = 1 << 5,
+ INTMAX = 1 << 6,
+ VOIDPTR = 1 << 7,
+ UNSIGNED = 1 << 8,
+ ALTFORM = 1 << 9,
+};
+
+#define MAXPREC 50
+
+struct conv {
+ int sign;
+ int prec;
+ char *digs;
+ int base;
+};
+
+static uintmax_t
+getnum(va_list *va, int flags, int *sign)
+{
+ uintmax_t uval;
+ intmax_t val;
+
+ if (flags & CHAR) {
+ val = va_arg(*va, int);
+ uval = (unsigned char) val;
+ } else if (flags & SHORT) {
+ val = va_arg(*va, int);
+ uval = (unsigned short) val;
+ } else if (flags & LONG) {
+ val = va_arg(*va, long);
+ uval = (unsigned long) val;
+ } else if (flags & LLONG) {
+ val = va_arg(*va, long long);
+ uval = (unsigned long long) val;
+ } else if (flags & SIZET) {
+ uval = va_arg(*va, size_t);
+ } else if (flags & INTMAX) {
+ val = va_arg(*va, intmax_t);
+ uval = (uintmax_t) val;
+ } else if (flags & VOIDPTR) {
+ uval = (uintmax_t) va_arg(*va, void *);
+ } else {
+ val = va_arg(*va, int);
+ uval = (unsigned) val;
+ }
+
+ if ((flags & UNSIGNED) == 0 && val < 0) {
+ *sign = '-';
+ uval = -uval;
+ }
+ return uval;
+}
+
+static char *
+numtostr(uintmax_t val, int flags, struct conv *conv, char *buf)
+{
+ char *buf0 = buf;
+ int base = conv->base, prec = conv->prec;
+ uintmax_t oval = val;
+
+ if (prec == -1)
+ prec = 1;
+
+ for (*buf = '\0'; val > 0; val /= base)
+ *--buf = conv->digs[val % base];
+ while (buf0 - buf < prec)
+ *--buf = '0';
+
+ if (flags & ALTFORM) {
+ if (base == 8 && *buf != '0') {
+ *--buf = '0';
+ } else if (base == 16 && oval != 0) {
+ *--buf = conv->digs[16];
+ *--buf = '0';
+ }
+ }
+ if (conv->sign)
+ *--buf = conv->sign;
+
+ return buf;
+}
+
+static void
+savecnt(va_list *va, int flags, int cnt)
+{
+ if (flags & CHAR)
+ *va_arg(*va, char*) = cnt;
+ else if (flags & SHORT)
+ *va_arg(*va, short*) = cnt;
+ else if (flags & LONG)
+ *va_arg(*va, long*) = cnt;
+ else if (flags & LLONG)
+ *va_arg(*va, long long*) = cnt;
+ else if (flags & SIZET)
+ *va_arg(*va, size_t*) = cnt;
+ else if (flags & INTMAX)
+ *va_arg(*va, intmax_t*) = cnt;
+ else
+ *va_arg(*va, int*) = cnt;
+}
+
+static size_t
+strout(char *s, size_t len, int width, int fill, FILE * restrict fp)
+{
+ int left = 0, adjust, ch, prefix;
+ size_t cnt = 0;
+
+ if (width < 0) {
+ left = 1;
+ width = -width;
+ }
+
+ adjust = (len < width) ? width - len : 0;
+ cnt = adjust + len;
+ if (left)
+ adjust = -adjust;
+
+ if (fill == '0') {
+ if (*s == '-' || *s == '+')
+ prefix = 1;
+ else if (*s == '0' && toupper(s[1]) == 'X')
+ prefix = 2;
+ else
+ prefix = 0;
+ while (prefix--) {
+ putc(*s++, fp);
+ --len;
+ }
+ }
+
+ for ( ; adjust > 0; adjust--)
+ putc(fill, fp);
+
+ while (ch = *s++)
+ putc(ch, fp);
+
+ for ( ; adjust < 0; adjust++)
+ putc(' ', fp);
+
+ return cnt;
+}
+
+int
+vfprintf(FILE * restrict fp, const char *fmt, va_list va)
+{
+ int ch, n, flags, width, left, fill, cnt = 0;
+ size_t inc, len;
+ char *s;
+ struct conv conv;
+ char buf[MAXPREC+1];
+ va_list va2;
+
+ va_copy(va2, va);
+ for (cnt = 0; ch = *fmt++; cnt += inc) {
+ if (ch != '%') {
+ putc(ch, fp);
+ inc = 1;
+ continue;
+ }
+
+ fill = ' ';
+ left = flags = width = 0;
+ conv.prec = -1;
+ conv.base = 10;
+ conv.sign = '\0';
+ conv.digs = "0123456789ABCDEFX";
+
+flags:
+ switch (*fmt++) {
+ case ' ':
+ if (conv.sign == '\0')
+ conv.sign = ' ';
+ goto flags;
+ case '+':
+ conv.sign = '+';
+ goto flags;
+ case '#':
+ flags |= ALTFORM;
+ goto flags;
+ case '.':
+ if (*fmt == '*') {
+ fmt++;
+ n = va_arg(va2, int);
+ } else {
+ for (n = 0; isdigit(ch = *fmt); fmt++)
+ n = n * 10 + ch - '0';
+ }
+ if (n > MAXPREC)
+ n = MAXPREC;
+ if (n > 0)
+ conv.prec = n;
+ goto flags;
+ case '*':
+ width = va_arg(va2, int);
+ goto flags;
+ case '-':
+ left = 1;
+ ++fmt;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ --fmt;
+ for (n = 0; isdigit(ch = *fmt); ++fmt)
+ n = n * 10 + ch - '0';
+ if (left)
+ n = -n;
+ width = n;
+ goto flags;
+ case '0':
+ fill = '0';
+ goto flags;
+ case 'l':
+ flags += LONG;
+ goto flags;
+ case 'h':
+ flags += SHORT;
+ goto flags;
+ case '%':
+ ch = '%';
+ goto cout;
+ case 'c':
+ ch = va_arg(va2, int);
+ cout:
+ buf[0] = ch;
+ buf[1] = '\0';
+ s = buf;
+ len = 1;
+ goto strout;
+ case 'j':
+ flags |= INTMAX;
+ goto flags;
+ case 't':
+ flags |= PTRDIFF;
+ goto flags;
+ case 'z':
+ flags |= SIZET;
+ goto flags;
+ case 'u':
+ flags |= UNSIGNED;
+ case 'i':
+ case 'd':
+ conv.base = 10;
+ goto numeric;
+ case 'p':
+ flags |= VOIDPTR | ALTFORM;
+ goto numeric16;
+ case 'x':
+ conv.digs = "0123456789abcdefx";
+ case 'X':
+ numeric16:
+ conv.base = 16;
+ flags |= UNSIGNED;
+ goto numeric;
+ case 'o':
+ conv.base = 8;
+ flags |= UNSIGNED;
+ numeric:
+ if (conv.prec != -1)
+ fill = ' ';
+ s = numtostr(getnum(&va2, flags, &conv.sign),
+ flags,
+ &conv,
+ &buf[MAXPREC]);
+ len = &buf[MAXPREC] - s;
+ goto strout;
+ case 'L':
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ /* TODO */
+ case 's':
+ s = va_arg(va2, char *);
+ len = strnlen(s, conv.prec);
+ strout:
+ inc = strout(s, len, width, fill, fp);
+ break;
+ case 'n':
+ savecnt(&va2, flags, cnt);
+ break;
+ case '\0':
+ goto out_loop;
+ }
+ }
+
+out_loop:
+ return (ferror(fp)) ? EOF : cnt;
+}
diff --git a/src/libc/vsnprintf.c b/src/libc/vsnprintf.c
@@ -0,0 +1,25 @@
+#include <stdarg.h>
+#include <stdio.h>
+#undef vsnprintf
+
+int
+vsnprintf(char * restrict s, size_t siz, const char * restrict fmt, va_list ap)
+{
+ FILE f;
+ int r;
+
+ f.flags = _IORW | _IOSTRG;
+ f.len = siz;
+ f.buf = s;
+ f.wp = s;
+ f.rp = s + siz;
+
+ r = vfprintf(&f, fmt, ap);
+ if (s) {
+ if (f.wp == f.rp)
+ --f.wp;
+ *f.wp = '\0';
+ }
+
+ return r;
+}
diff --git a/src/libc/vsprintf.c b/src/libc/vsprintf.c
@@ -0,0 +1,12 @@
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#undef vsprintf
+
+
+int
+vsprintf(char * restrict s, const char * restrict fmt, va_list va)
+{
+ return vsnprintf(s, SIZE_MAX, fmt, va);
+}
diff --git a/src/librmu/Makefile b/src/librmu/Makefile
@@ -0,0 +1,54 @@
+PROJECTDIR=../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+OBJS = RMU_Crypto_Random.o \
+ RMU_Local_Load.o \
+ RMU_Local_Status.o \
+ RMU_Local_Validate.o \
+ RMU_REC_Prepare.o \
+ RMU_REC_ReadGeneralPurposeRegister.o \
+ RMU_REC_ReadSystemRegister.o \
+ RMU_REC_ReadVectorRegister.o \
+ RMU_REC_Register.o \
+ RMU_REC_Release.o \
+ RMU_REC_Size.o \
+ RMU_REC_WriteGeneralPurposeRegister.o \
+ RMU_REC_WriteSystemRegister.o \
+ RMU_REC_WriteVectorRegister.o \
+ RMU_Realm_Activate.o \
+ RMU_Realm_AttestationReport.o \
+ RMU_Realm_AttestationReportInit.o \
+ RMU_Realm_AttestationReportSize.o \
+ RMU_Realm_CreateZeroMetadata.o \
+ RMU_Realm_DeriveBindingKey.o \
+ RMU_Realm_ExtendBindingKeySeedValue.o \
+ RMU_Realm_GetBindingKeySeedValue.o \
+ RMU_Realm_GetMetadata.o \
+ RMU_Realm_GetParameterInheritance.o \
+ RMU_Realm_GetParameterValue.o \
+ RMU_Realm_Info.o \
+ RMU_Realm_Initialize.o \
+ RMU_Realm_Invalidate.o \
+ RMU_Realm_InvalidateCurrent.o \
+ RMU_Realm_Populate.o \
+ RMU_Realm_Prepare.o \
+ RMU_Realm_ReadMemory.o \
+ RMU_Realm_Register.o \
+ RMU_Realm_Release.o \
+ RMU_Realm_SetBindingKeySeedLock.o \
+ RMU_Realm_SetCommandTrap.o \
+ RMU_Realm_SetMetadata.o \
+ RMU_Realm_SetParameterInheritance.o \
+ RMU_Realm_SetParameterValue.o \
+ RMU_Realm_WriteMemory.o \
+ RMU_System_Enable.o \
+ RMU_System_InterfaceVersion.o \
+ RMU_System_Status.o \
+
+TARGET = $(LIBDIR)/librmu.a
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $?
+ ranlib $@
diff --git a/src/librmu/RMU_Crypto_Random.c b/src/librmu/RMU_Crypto_Random.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Crypto_Random(void)
+{
+ dbg("RMU_Crypto_Random\n");
+}
diff --git a/src/librmu/RMU_Local_Load.c b/src/librmu/RMU_Local_Load.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Local_Load(void)
+{
+ dbg("RMU_Local_Load\n");
+}
diff --git a/src/librmu/RMU_Local_Status.c b/src/librmu/RMU_Local_Status.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Local_Status(void)
+{
+ dbg("RMU_Local_Status\n");
+}
diff --git a/src/librmu/RMU_Local_Validate.c b/src/librmu/RMU_Local_Validate.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Local_Validate(void)
+{
+ dbg("RMU_Local_Validate\n");
+}
diff --git a/src/librmu/RMU_REC_Prepare.c b/src/librmu/RMU_REC_Prepare.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_REC_Prepare(void)
+{
+ dbg("RMU_REC_Prepare\n");
+}
diff --git a/src/librmu/RMU_REC_ReadGeneralPurposeRegister.c b/src/librmu/RMU_REC_ReadGeneralPurposeRegister.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_REC_ReadGeneralPurposeRegister(void)
+{
+ dbg("RMU_REC_ReadGeneralPurposeRegister\n");
+}
diff --git a/src/librmu/RMU_REC_ReadSystemRegister.c b/src/librmu/RMU_REC_ReadSystemRegister.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_REC_ReadSystemRegister(void)
+{
+ dbg("RMU_REC_ReadSystemRegister\n");
+}
diff --git a/src/librmu/RMU_REC_ReadVectorRegister.c b/src/librmu/RMU_REC_ReadVectorRegister.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_REC_ReadVectorRegister(void)
+{
+ dbg("RMU_REC_ReadVectorRegister\n");
+}
diff --git a/src/librmu/RMU_REC_Register.c b/src/librmu/RMU_REC_Register.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_REC_Register(void)
+{
+ dbg("RMU_REC_Register\n");
+}
diff --git a/src/librmu/RMU_REC_Release.c b/src/librmu/RMU_REC_Release.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_REC_Release(void)
+{
+ dbg("RMU_REC_Release\n");
+}
diff --git a/src/librmu/RMU_REC_Size.c b/src/librmu/RMU_REC_Size.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_REC_Size(void)
+{
+ dbg("RMU_REC_Size\n");
+}
diff --git a/src/librmu/RMU_REC_WriteGeneralPurposeRegister.c b/src/librmu/RMU_REC_WriteGeneralPurposeRegister.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_REC_WriteGeneralPurposeRegister(void)
+{
+ dbg("RMU_REC_WriteGeneralPurposeRegister\n");
+}
diff --git a/src/librmu/RMU_REC_WriteSystemRegister.c b/src/librmu/RMU_REC_WriteSystemRegister.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_REC_WriteSystemRegister(void)
+{
+ dbg("RMU_REC_WriteSystemRegister\n");
+}
diff --git a/src/librmu/RMU_REC_WriteVectorRegister.c b/src/librmu/RMU_REC_WriteVectorRegister.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_REC_WriteVectorRegister(void)
+{
+ dbg("RMU_REC_WriteVectorRegister\n");
+}
diff --git a/src/librmu/RMU_Realm_Activate.c b/src/librmu/RMU_Realm_Activate.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_Activate(void)
+{
+ dbg("RMU_Realm_Activate\n");
+}
diff --git a/src/librmu/RMU_Realm_AttestationReport.c b/src/librmu/RMU_Realm_AttestationReport.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_AttestationReport(void)
+{
+ dbg("RMU_Realm_AttestationReport\n");
+}
diff --git a/src/librmu/RMU_Realm_AttestationReportInit.c b/src/librmu/RMU_Realm_AttestationReportInit.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_AttestationReportInit(void)
+{
+ dbg("RMU_Realm_AttestationReportInit\n");
+}
diff --git a/src/librmu/RMU_Realm_AttestationReportSize.c b/src/librmu/RMU_Realm_AttestationReportSize.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_AttestationReportSize(void)
+{
+ dbg("RMU_Realm_AttestationReportSize\n");
+}
diff --git a/src/librmu/RMU_Realm_CreateZeroMetadata.c b/src/librmu/RMU_Realm_CreateZeroMetadata.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_CreateZeroMetadata(void)
+{
+ dbg("RMU_Realm_CreateZeroMetadata\n");
+}
diff --git a/src/librmu/RMU_Realm_DeriveBindingKey.c b/src/librmu/RMU_Realm_DeriveBindingKey.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_DeriveBindingKey(void)
+{
+ dbg("RMU_Realm_DeriveBindingKey\n");
+}
diff --git a/src/librmu/RMU_Realm_ExtendBindingKeySeedValue.c b/src/librmu/RMU_Realm_ExtendBindingKeySeedValue.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_ExtendBindingKeySeedValue(void)
+{
+ dbg("RMU_Realm_ExtendBindingKeySeedValue\n");
+}
diff --git a/src/librmu/RMU_Realm_GetBindingKeySeedValue.c b/src/librmu/RMU_Realm_GetBindingKeySeedValue.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_GetBindingKeySeedValue(void)
+{
+ dbg("RMU_Realm_GetBindingKeySeedValue\n");
+}
diff --git a/src/librmu/RMU_Realm_GetMetadata.c b/src/librmu/RMU_Realm_GetMetadata.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_GetMetadata(void)
+{
+ dbg("RMU_Realm_GetMetadata\n");
+}
diff --git a/src/librmu/RMU_Realm_GetParameterInheritance.c b/src/librmu/RMU_Realm_GetParameterInheritance.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_GetParameterInheritance(void)
+{
+ dbg("RMU_Realm_GetParameterInheritance\n");
+}
diff --git a/src/librmu/RMU_Realm_GetParameterValue.c b/src/librmu/RMU_Realm_GetParameterValue.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_GetParameterValue(void)
+{
+ dbg("RMU_Realm_GetParameterValue\n");
+}
diff --git a/src/librmu/RMU_Realm_Info.c b/src/librmu/RMU_Realm_Info.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_Info(void)
+{
+ dbg("RMU_Realm_Info\n");
+}
diff --git a/src/librmu/RMU_Realm_Initialize.c b/src/librmu/RMU_Realm_Initialize.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_Initialize(void)
+{
+ dbg("RMU_Realm_Initialize\n");
+}
diff --git a/src/librmu/RMU_Realm_Invalidate.c b/src/librmu/RMU_Realm_Invalidate.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_Invalidate(void)
+{
+ dbg("RMU_Realm_Invalidate\n");
+}
diff --git a/src/librmu/RMU_Realm_InvalidateCurrent.c b/src/librmu/RMU_Realm_InvalidateCurrent.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_InvalidateCurrent(void)
+{
+ dbg("RMU_Realm_InvalidateCurrent\n");
+}
diff --git a/src/librmu/RMU_Realm_Populate.c b/src/librmu/RMU_Realm_Populate.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_Populate(void)
+{
+ dbg("RMU_Realm_Populate\n");
+}
diff --git a/src/librmu/RMU_Realm_Prepare.c b/src/librmu/RMU_Realm_Prepare.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_Prepare(void)
+{
+ dbg("RMU_Realm_Prepare\n");
+}
diff --git a/src/librmu/RMU_Realm_ReadMemory.c b/src/librmu/RMU_Realm_ReadMemory.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_ReadMemory(void)
+{
+ dbg("RMU_Realm_ReadMemory\n");
+}
diff --git a/src/librmu/RMU_Realm_Register.c b/src/librmu/RMU_Realm_Register.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_Register(void)
+{
+ dbg("RMU_Realm_Register\n");
+}
diff --git a/src/librmu/RMU_Realm_Release.c b/src/librmu/RMU_Realm_Release.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_Release(void)
+{
+ dbg("RMU_Realm_Release\n");
+}
diff --git a/src/librmu/RMU_Realm_SetBindingKeySeedLock.c b/src/librmu/RMU_Realm_SetBindingKeySeedLock.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_SetBindingKeySeedLock(void)
+{
+ dbg("RMU_Realm_SetBindingKeySeedLock\n");
+}
diff --git a/src/librmu/RMU_Realm_SetCommandTrap.c b/src/librmu/RMU_Realm_SetCommandTrap.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_SetCommandTrap(void)
+{
+ dbg("RMU_Realm_SetCommandTrap\n");
+}
diff --git a/src/librmu/RMU_Realm_SetMetadata.c b/src/librmu/RMU_Realm_SetMetadata.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_SetMetadata(void)
+{
+ dbg("RMU_Realm_SetMetadata\n");
+}
diff --git a/src/librmu/RMU_Realm_SetParameterInheritance.c b/src/librmu/RMU_Realm_SetParameterInheritance.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_SetParameterInheritance(void)
+{
+ dbg("RMU_Realm_SetParameterInheritance\n");
+}
diff --git a/src/librmu/RMU_Realm_SetParameterValue.c b/src/librmu/RMU_Realm_SetParameterValue.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_SetParameterValue(void)
+{
+ dbg("RMU_Realm_SetParameterValue\n");
+}
diff --git a/src/librmu/RMU_Realm_WriteMemory.c b/src/librmu/RMU_Realm_WriteMemory.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_Realm_WriteMemory(void)
+{
+ dbg("RMU_Realm_WriteMemory\n");
+}
diff --git a/src/librmu/RMU_System_Enable.c b/src/librmu/RMU_System_Enable.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_System_Enable(void)
+{
+ dbg("RMU_System_Enable\n");
+}
diff --git a/src/librmu/RMU_System_InterfaceVersion.c b/src/librmu/RMU_System_InterfaceVersion.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_System_InterfaceVersion(void)
+{
+ dbg("RMU_System_InterfaceVersion\n");
+}
diff --git a/src/librmu/RMU_System_Status.c b/src/librmu/RMU_System_Status.c
@@ -0,0 +1,7 @@
+#include <rcode.h>
+
+void
+RMU_System_Status(void)
+{
+ dbg("RMU_System_Status\n");
+}
diff --git a/src/libtypes/Makefile b/src/libtypes/Makefile
@@ -0,0 +1,13 @@
+PROJECTDIR=../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+OBJS = pack.o unpack.o
+TARGET = $(LIBDIR)/libtypes.a
+
+$(TARGET): $(OBJS)
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $?
+ ranlib $@
diff --git a/src/libtypes/pack.c b/src/libtypes/pack.c
@@ -0,0 +1,123 @@
+#include <stdarg.h>
+#include <stdint.h>
+
+#include <types.h>
+
+static uint64_t
+setbits(uint64_t dst, uint64_t src, int pos, int num)
+{
+ uint64_t mask;
+
+ if (num == 64) {
+ mask = 0;
+ } else {
+ mask = ~(~0ull << num);
+ mask = ~(mask << pos);
+ }
+
+ dst &= mask;
+ dst |= src << pos;
+ return dst;
+}
+
+/*
+ * This function stores a field of length `num` in the logical bitstream
+ * represented by `buf[]` with the value from `v` starting at
+ * position `pos`. Each word in `buf[]` is 64 bits. If the field
+ * spans 2 words in `buf[]` then the required bits of both words are stored.
+ */
+static void
+setfield(uint64_t buf[], uint64_t v, int pos, int num)
+{
+ int n, word, bit, rem;
+
+ word = pos / 64; /* 1st word of the field */
+ bit = pos % 64; /* offset in the 1st word */
+
+ n = (bit + num < 64) ? num : 64 - bit;
+ buf[word] = setbits(buf[word], v, bit, n);
+ rem = num - n;
+ if (rem != 0)
+ buf[word+1] = setbits(buf[word+1], v >> n, 0, rem);
+}
+
+int
+pack(uint64_t buf[], const char *fmt, ...)
+{
+ va_list va;
+ int pos, nbits, ret = -1;
+
+ va_start(va, fmt);
+ for (pos = 0; *fmt; pos += nbits) {
+ int d, size;
+ unsigned long long v;
+
+ nbits = 0;
+ if (*fmt == ' ') {
+ fmt++;
+ continue;
+ }
+
+ if (*fmt++ != '%')
+ goto err;
+
+ while (*fmt >= '0' && *fmt <= '9') {
+ d = *fmt++ - '0';
+ nbits = nbits * 10 + d;
+ }
+ if (nbits == 0)
+ goto err;
+
+ size = 0;
+flags:
+ switch (*fmt++) {
+ case 'c':
+ if (nbits > 8)
+ goto err;
+ v = va_arg(va, unsigned);
+ setfield(buf, v, pos, nbits);
+ break;
+ case 'h':
+ size = 1;
+ goto flags;
+ case 'l':
+ size += 2;
+ goto flags;
+ case 'u':
+ switch (size) {
+ case 0:
+ if (nbits > 16)
+ goto err;
+ v = va_arg(va, unsigned);
+ setfield(buf, v, pos, nbits);
+ break;
+ case 1:
+ if (nbits > 16)
+ goto err;
+ v = va_arg(va, unsigned);
+ setfield(buf, v, pos, nbits);
+ break;
+ case 2:
+ if (nbits > 32)
+ goto err;
+ v = va_arg(va, unsigned long);
+ setfield(buf, v, pos, nbits);
+ break;
+ case 4:
+ if (nbits > 64)
+ goto err;
+ v = va_arg(va, unsigned long long);
+ setfield(buf, v, pos, nbits);
+ break;
+ default:
+ goto err;
+ }
+ break;
+ }
+ }
+ va_end(va);
+
+ ret = nbits;
+err:
+ return ret;
+}
diff --git a/src/libtypes/unpack.c b/src/libtypes/unpack.c
@@ -0,0 +1,113 @@
+#include <stdarg.h>
+#include <stdint.h>
+
+#include <types.h>
+
+static uint64_t
+getbits(uint64_t v, int pos, int num)
+{
+ uint64_t mask = (num == 64) ? ~0ull : ~(~0ull << num);
+
+ return (v >> pos) & mask;
+}
+
+/*
+ * This function extracts a field of length `num` in the
+ * logical bitstream represented by `buf[]` starting at position `pos`.
+ * Each word in `buf[]` is 64 bits. If the field spans 2 words
+ * then it extracts the bits from the two words and returns the composed result.
+ */
+static uint64_t
+getfield(uint64_t buf[], int pos, int num)
+{
+ int n, word, bit, rem;
+ unsigned long long v;
+
+ word = pos / 64; /* 1st word of the field */
+ bit = pos % 64; /* offset in the 1st word */
+
+ n = (bit + num < 64) ? num : 64 - bit;
+ v = getbits(buf[word], bit, n);
+ rem = num - n;
+ if (rem != 0)
+ v |= getbits(buf[word+1], 0, rem) << n;
+
+ return v;
+}
+
+int
+unpack(uint64_t buf[], const char *fmt, ...)
+{
+ va_list va;
+ int pos, nbits, ret = -1;
+
+ va_start(va, fmt);
+ for (pos = 0; *fmt; pos += nbits) {
+ int d, size;
+ unsigned long long v;
+
+ nbits = 0;
+ if (*fmt == ' ') {
+ fmt++;
+ continue;
+ }
+
+ if (*fmt++ != '%')
+ goto err;
+
+ while (*fmt >= '0' && *fmt <= '9') {
+ d = *fmt++ - '0';
+ nbits = nbits * 10 + d;
+ }
+ if (nbits == 0)
+ goto err;
+
+ size = 0;
+ v = getfield(buf, pos, nbits);
+flags:
+ switch (*fmt++) {
+ case 'c':
+ if (nbits > 8)
+ goto err;
+ *va_arg(va, unsigned char *) = v;
+ break;
+ case 'h':
+ size = 1;
+ goto flags;
+ case 'l':
+ size += 2;
+ goto flags;
+ case 'u':
+ switch (size) {
+ case 0:
+ if (nbits > 16)
+ goto err;
+ *va_arg(va, unsigned *) = v;
+ break;
+ case 1:
+ if (nbits > 16)
+ goto err;
+ *va_arg(va, unsigned short *) = v;
+ break;
+ case 2:
+ if (nbits > 32)
+ goto err;
+ *va_arg(va, unsigned long *) = v;
+ break;
+ case 4:
+ if (nbits > 64)
+ goto err;
+ *va_arg(va, unsigned long long *) = v;
+ break;
+ default:
+ goto err;
+ }
+ break;
+ }
+ }
+ va_end(va);
+
+ ret = nbits;
+err:
+ return ret;
+}
diff --git a/src/ramfw/Makefile b/src/ramfw/Makefile
@@ -0,0 +1,16 @@
+PROJECTDIR=../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+OBJS = ../rmc.o \
+ rmctbl.o \
+
+all: builtin.o
+
+builtin.o: $(OBJS)
+ $(LD) $(RCODE_LDFLAGS) -r -o $@ $(OBJS)
+
+rmctbl.c: $(SCRIPTDIR)/rmu.cmd
+ $(SCRIPTDIR)/gentbl.sh -o $@ -i $(SCRIPTDIR)/rmu.cmd
+
+clean:
+ rm -f rmctbl.c
diff --git a/src/rmc.c b/src/rmc.c
@@ -0,0 +1,52 @@
+#include <rcode.h>
+
+void
+bad_rmc(Ctx *ctx, int error)
+{
+ dbg("bad RMC: %d, %d = %d\n", ctx->imm1, ctx->imm2, error);
+ ctx->error = error;
+ longjmp(ctx->recover, 1);
+}
+
+/*
+ * The dispatcher cannot be implemented using a table
+ * because the rmu command number is composed by two
+ * immediates, imm1 and imm2, which don't generate
+ * consecutive values. The approach is to use a sparse
+ * matrix, where we store all the function pointers
+ * consecutive and we create a row index table which
+ * the offset from the beginning of the handler table
+ * and number of entries in that table for that row.
+ *
+ * rowidx handler
+ * --------------- --------
+ * | off = 0,cnt=1 | | fun0 |
+ * --------------- --------
+ * imm1--> | off = 1,cnt=2 | ---> off + imm2 --> | fun1 |
+ * --------------- --------
+ * | off = 3,cnt=1 | | fun2 |
+ * --------------- --------
+ * ... ...
+ */
+void
+rmc(unsigned imm1, unsigned imm2, Ctx *ctx)
+{
+ const struct rowidx *idx;
+
+ if (setjmp(ctx->recover))
+ return;
+
+ if (imm1 > 255 || imm2 > 255)
+ panic("rmc");
+
+ ctx->imm1 = imm1;
+ ctx->imm2 = imm2;
+
+ idx = &rowidx[imm1];
+ if (imm2 >= idx->cnt)
+ bad_rmc(ctx, 1);
+
+ (*handler[idx->off + imm2])();
+
+ ctx->error = 0;
+}
diff --git a/src/romfw/Makefile b/src/romfw/Makefile
@@ -0,0 +1,16 @@
+PROJECTDIR=../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+OBJS = ../rmc.o \
+ rmctbl.o \
+
+all: builtin.o
+
+builtin.o: $(OBJS)
+ $(LD) $(RCODE_LDFLAGS) -r -o $@ $(OBJS)
+
+rmctbl.c: $(SCRIPTDIR)/rmu.cmd
+ $(SCRIPTDIR)/gentbl.sh -o $@ -i $(SCRIPTDIR)/rmu.cmd
+
+clean:
+ rm -f rmctbl.c
diff --git a/src/romfw/rmc.c b/src/romfw/rmc.c
@@ -0,0 +1,33 @@
+#include <rcode.h>
+
+void
+bad_rmc(Ctx *ctx, int error)
+{
+ dbg("bad RMC: %d, %d = %d\n", ctx->imm1, ctx->imm2, error);
+ ctx->error = error;
+ longjmp(ctx->recover, 1);
+}
+
+void
+rmc(unsigned imm1, unsigned imm2, Ctx *ctx)
+{
+ const struct rowidx *idx;
+ int offset;
+
+ if (setjmp(ctx->recover))
+ return;
+
+ if (imm1 > 255 || imm2 > 255)
+ panic("rmc");
+
+ ctx->imm1 = imm1;
+ ctx->imm2 = imm2;
+
+ idx = &rowidx[imm1];
+ if (imm2 >= idx->cnt)
+ bad_rmc(ctx, 1);
+
+ (*handler[idx->off + imm2])();
+
+ ctx->error = 0;
+}
diff --git a/test/.gitignore b/test/.gitignore
@@ -0,0 +1,2 @@
+test.log
+run
diff --git a/test/Makefile b/test/Makefile
@@ -0,0 +1,16 @@
+PROJECTDIR = ..
+include $(PROJECTDIR)/scripts/rules.mk
+
+DIRS = test1 test2
+
+all: $(DIRS)
+
+test: FORCE
+ @MAKE=$(MAKE) ./chktest.sh
+
+$(DIRS): FORCE
+ +@cd $@ && $(MAKE)
+
+clean:
+ $(FORALL)
+ rm -f test.log
diff --git a/test/chktest.sh b/test/chktest.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+rm -f test.log
+pwd=$PWD
+
+for i in test*
+do
+ cd $i &&
+ $MAKE run_test >> ../test.log 2>&1 &&
+ printf '[PASS]' || printf '[FAIL]'
+ printf "\t%s\n" $i
+ cd $pwd
+done
diff --git a/test/test1/.gitignore b/test/test1/.gitignore
@@ -0,0 +1,43 @@
+RMU_Crypto_Random.c
+RMU_Local_Load.c
+RMU_Local_Status.c
+RMU_Local_Validate.c
+RMU_REC_Prepare.c
+RMU_REC_ReadGeneralPurposeRegister.c
+RMU_REC_ReadSystemRegister.c
+RMU_REC_ReadVectorRegister.c
+RMU_REC_Register.c
+RMU_REC_Release.c
+RMU_REC_Size.c
+RMU_REC_WriteGeneralPurposeRegister.c
+RMU_REC_WriteSystemRegister.c
+RMU_REC_WriteVectorRegister.c
+RMU_Realm_Activate.c
+RMU_Realm_AttestationReport.c
+RMU_Realm_AttestationReportInit.c
+RMU_Realm_AttestationReportSize.c
+RMU_Realm_CreateZeroMetadata.c
+RMU_Realm_DeriveBindingKey.c
+RMU_Realm_ExtendBindingKeySeedValue.c
+RMU_Realm_GetBindingKeySeedValue.c
+RMU_Realm_GetMetadata.c
+RMU_Realm_GetParameterInheritance.c
+RMU_Realm_GetParameterValue.c
+RMU_Realm_Info.c
+RMU_Realm_Initialize.c
+RMU_Realm_Invalidate.c
+RMU_Realm_InvalidateCurrent.c
+RMU_Realm_Populate.c
+RMU_Realm_Prepare.c
+RMU_Realm_ReadMemory.c
+RMU_Realm_Register.c
+RMU_Realm_Release.c
+RMU_Realm_SetBindingKeySeedLock.c
+RMU_Realm_SetCommandTrap.c
+RMU_Realm_SetMetadata.c
+RMU_Realm_SetParameterInheritance.c
+RMU_Realm_SetParameterValue.c
+RMU_Realm_WriteMemory.c
+RMU_System_Enable.c
+RMU_System_InterfaceVersion.c
+RMU_System_Status.c
diff --git a/test/test1/Makefile b/test/test1/Makefile
@@ -0,0 +1,69 @@
+PROJECTDIR = ../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+LIBOBJ = RMU_Crypto_Random.o \
+ RMU_Local_Load.o \
+ RMU_Local_Status.o \
+ RMU_Local_Validate.o \
+ RMU_REC_Prepare.o \
+ RMU_REC_ReadGeneralPurposeRegister.o \
+ RMU_REC_ReadSystemRegister.o \
+ RMU_REC_ReadVectorRegister.o \
+ RMU_REC_Register.o \
+ RMU_REC_Release.o \
+ RMU_REC_Size.o \
+ RMU_REC_WriteGeneralPurposeRegister.o \
+ RMU_REC_WriteSystemRegister.o \
+ RMU_REC_WriteVectorRegister.o \
+ RMU_Realm_Activate.o \
+ RMU_Realm_AttestationReport.o \
+ RMU_Realm_AttestationReportInit.o \
+ RMU_Realm_AttestationReportSize.o \
+ RMU_Realm_CreateZeroMetadata.o \
+ RMU_Realm_DeriveBindingKey.o \
+ RMU_Realm_ExtendBindingKeySeedValue.o \
+ RMU_Realm_GetBindingKeySeedValue.o \
+ RMU_Realm_GetMetadata.o \
+ RMU_Realm_GetParameterInheritance.o \
+ RMU_Realm_GetParameterValue.o \
+ RMU_Realm_Info.o \
+ RMU_Realm_Initialize.o \
+ RMU_Realm_Invalidate.o \
+ RMU_Realm_InvalidateCurrent.o \
+ RMU_Realm_Populate.o \
+ RMU_Realm_Prepare.o \
+ RMU_Realm_ReadMemory.o \
+ RMU_Realm_Register.o \
+ RMU_Realm_Release.o \
+ RMU_Realm_SetBindingKeySeedLock.o \
+ RMU_Realm_SetCommandTrap.o \
+ RMU_Realm_SetMetadata.o \
+ RMU_Realm_SetParameterInheritance.o \
+ RMU_Realm_SetParameterValue.o \
+ RMU_Realm_WriteMemory.o \
+ RMU_System_Enable.o \
+ RMU_System_InterfaceVersion.o \
+ RMU_System_Status.o \
+
+OBJS = $(ARCHDIR)/crt-$(SYS).o $(SRCDIR)/romfw/builtin.o test.o
+LIBS = -lrmu -lc
+LIBDEP = librmu.a $(LIBDIR)/libc.a
+
+TARGET = run
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS) $(LIBDEP)
+ $(LD) $(RCODE_LDFLAGS) $(OBJS) $(LIBS) -o $@
+
+librmu.a: $(LIBOBJ)
+ $(AR) $(ARFLAGS) $@ $?
+ ranlib $@
+
+$(LIBOBJ): $(LIBOBJ:.o=.c)
+
+$(LIBOBJ:.o=.c): genrmu.sh
+ ./genrmu.sh
+
+clean:
+ rm -f $(LIBOBJ:.o=.c) *.a
diff --git a/test/test1/genrmu.sh b/test/test1/genrmu.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+genfile()
+{
+ cat <<FILE >$i.c
+#include <rcode.h>
+
+void
+$1(void)
+{
+ dbg("$1\n");
+}
+FILE
+}
+
+
+cat <<EOF | while read i; do genfile $i; done
+RMU_REC_WriteVectorRegister
+RMU_Realm_SetMetadata
+RMU_Realm_GetParameterValue
+RMU_REC_ReadSystemRegister
+RMU_Realm_GetMetadata
+RMU_Realm_SetParameterValue
+RMU_REC_WriteSystemRegister
+RMU_Realm_CreateZeroMetadata
+RMU_Realm_GetParameterInheritance
+RMU_Realm_SetParameterInheritance
+RMU_Realm_Initialize
+RMU_Realm_Prepare
+RMU_Local_Status
+RMU_Realm_Populate
+RMU_Local_Load
+RMU_Realm_Activate
+RMU_Local_Validate
+RMU_Realm_Info
+RMU_Realm_SetCommandTrap
+RMU_Crypto_Random
+RMU_Realm_AttestationReportSize
+RMU_Realm_AttestationReportInit
+RMU_Realm_AttestationReport
+RMU_Realm_Register
+RMU_Realm_Release
+RMU_Realm_ExtendBindingKeySeedValue
+RMU_Realm_SetBindingKeySeedLock
+RMU_Realm_DeriveBindingKey
+RMU_Realm_GetBindingKeySeedValue
+RMU_Realm_InvalidateCurrent
+RMU_REC_Size
+RMU_REC_Register
+RMU_System_InterfaceVersion
+RMU_REC_Prepare
+RMU_System_Status
+RMU_REC_Release
+RMU_System_Enable
+RMU_REC_ReadGeneralPurposeRegister
+RMU_REC_WriteGeneralPurposeRegister
+RMU_Realm_ReadMemory
+RMU_REC_ReadVectorRegister
+RMU_Realm_WriteMemory
+RMU_Realm_Invalidate
+EOF
diff --git a/test/test1/test.c b/test/test1/test.c
@@ -0,0 +1,26 @@
+#include <assert.h>
+
+#include <rcode.h>
+
+int
+main(int argc, char *argv[])
+{
+ unsigned i, j;
+ Ctx ctx;
+
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 256; j++) {
+ dbg("%u\t%u\t", i, j);
+ rmc(i, j, &ctx);
+ }
+ }
+ return 0;
+}
+
+void
+panic(const char *msg)
+{
+ printk("panic: %s\n", msg);
+ for (;;)
+ ;
+}
diff --git a/test/test1/test.sh b/test/test1/test.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+set -e
+
+tmp1=`mktemp`
+tmp2=`mktemp`
+trap "rm -f $tmp1 $tmp2;exit 1" EXIT INT QUIT TERM
+
+$EMUCMD ./run | grep -v 'bad RMC' > $tmp1
+sed 's/\./_/g' < $SCRIPTDIR/rmu.cmd > $tmp2
+diff -u $tmp1 $tmp2
+
+$EMUCMD ./run | awk '
+/[0-9]+ [0-9]+/ {rmc[$1, $2] = 1}
+END {
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 256; j++) {
+ if (!rmc[i, j]) {
+ print "fail", i, j
+ exit 1
+ }
+ }
+ }
+}'
+
+rm $tmp1 $tmp2
+trap - EXIT
diff --git a/test/test2/Makefile b/test/test2/Makefile
@@ -0,0 +1,13 @@
+PROJECTDIR = ../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+OBJS = $(ARCHDIR)/crt-$(SYS).o test.o
+LIBS = -ltypes -lc
+LIBDEP = $(LIBDIR)/libtypes.a $(LIBDIR)/libc.a
+
+TARGET = run
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS) $(LIBDEP)
+ $(LD) $(RCODE_LDFLAGS) $(OBJS) $(LIBS) -o $@
diff --git a/test/test2/test.c b/test/test2/test.c
@@ -0,0 +1,189 @@
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <types.h>
+
+#define ITER 1048576*4
+
+void
+test_pack(void)
+{
+ uint64_t buf[2];
+ unsigned long long v1 = 1, v2 = 0, msb;
+ int i;
+
+ for (i = 0; i < 128; i++) {
+ pack(buf, "%64llu %64llu", v1, v2);
+ printf("0x%llx 0x%llx\n", buf[1], buf[0]);
+ msb = v1 & 1ull << 63;
+ v1 <<= 1;
+ v2 <<= 1;
+ v2 |= msb != 0;
+ }
+}
+
+void
+test_unpack(void)
+{
+ uint64_t buf[2];
+ unsigned long long v1 = 1, v2 = 0, msb;
+ int i;
+
+ buf[0] = 1;
+ buf[1] = 0;
+ for (i = 0; i < 128; i++) {
+ unpack(buf, "%64llu %64llu", &v1, &v2);
+ printf("0x%llx 0x%llx\n", v2, v1);
+ msb = buf[0] & 1ull << 63;
+ buf[0] <<= 1;
+ buf[1] <<= 1;
+ buf[1] |= msb != 0;
+ }
+}
+
+long long
+rand64(void)
+{
+ unsigned long long v, i;
+
+ for (v = i = 0; i < sizeof(v); i++) {
+ v <<= CHAR_BIT;
+ v |= rand() % UCHAR_MAX;
+ }
+ return v;
+}
+
+void
+test_pack_unpack_c(uint64_t buf[])
+{
+ char fmt[32];
+ unsigned char v1, v2, v3, v4;
+ int b1, b2;
+
+ v1 = rand64();
+ v2 = rand64();
+ b1 = (rand() % 8) + 1;
+ b2 = (rand() % 8) + 1;
+ v1 &= ~(~0ull << b1);
+ v2 &= ~(~0ull << b2);
+ snprintf(fmt, sizeof(fmt), "%%%dc %%%dc", b1, b2);
+ assert(pack(buf, fmt, v1, v2) != -1);
+ assert(unpack(buf, fmt, &v3, &v4) != -1);
+ assert(v1 == v3 && v2 == v4);
+}
+
+void
+test_pack_unpack_h(uint64_t buf[])
+{
+ char fmt[32];
+ unsigned short v1, v2, v3, v4;
+ int b1, b2;
+
+ v1 = rand64();
+ v2 = rand64();
+ b1 = (rand() % 16) + 1;
+ b2 = (rand() % 16) + 1;
+ v1 &= ~(~0ull << b1);
+ v2 &= ~(~0ull << b2);
+ snprintf(fmt, sizeof(fmt), "%%%dhu %%%dhu", b1, b2);
+ assert(pack(buf, fmt, v1, v2) != -1);
+ assert(unpack(buf, fmt, &v3, &v4) != -1);
+ assert(v1 == v3 && v2 == v4);
+}
+
+void
+test_pack_unpack_u(uint64_t buf[])
+{
+ char fmt[32];
+ unsigned int v1, v2, v3, v4;
+ int b1, b2;
+
+ v1 = rand64();
+ v2 = rand64();
+ b1 = (rand() % 16) + 1;
+ b2 = (rand() % 16) + 1;
+ v1 &= ~(~0ull << b1);
+ v2 &= ~(~0ull << b2);
+ snprintf(fmt, sizeof(fmt), "%%%du %%%du", b1, b2);
+ assert(pack(buf, fmt, v1, v2) != -1);
+ assert(unpack(buf, fmt, &v3, &v4) != -1);
+ assert(v1 == v3 && v2 == v4);
+}
+
+void
+test_pack_unpack_lu(uint64_t buf[])
+{
+ char fmt[32];
+ unsigned long v1, v2, v3, v4;
+ int b1, b2;
+
+ v1 = rand64();
+ v2 = rand64();
+ b1 = (rand() % 32) + 1;
+ b2 = (rand() % 32) + 1;
+ v1 &= ~(~0ull << b1);
+ v2 &= ~(~0ull << b2);
+ snprintf(fmt, sizeof(fmt), "%%%dlu %%%dlu", b1, b2);
+ assert(pack(buf, fmt, v1, v2) != -1);
+ assert(unpack(buf, fmt, &v3, &v4) != -1);
+ assert(v1 == v3 && v2 == v4);
+}
+
+void
+test_pack_unpack_llu(uint64_t buf[])
+{
+ char fmt[32];
+ unsigned long long v1, v2, v3, v4;
+ int b1, b2;
+
+ v1 = rand64();
+ v2 = rand64();
+ b1 = (rand() % 64) + 1;
+ b2 = (rand() % 64) + 1;
+ v1 &= ~(~0ull << b1);
+ v2 &= ~(~0ull << b2);
+ snprintf(fmt, sizeof(fmt), "%%%dllu %%%dllu", b1, b2);
+ assert(pack(buf, fmt, v1, v2) != -1);
+ assert(unpack(buf, fmt, &v3, &v4) != -1);
+ assert(v1 == v3 && v2 == v4);
+}
+
+void
+test_pack_unpack(void)
+{
+ uint64_t buf[2] = { 0 };
+ unsigned long long i;
+
+ for (i = 0; i < ITER; i++) {
+ switch (rand() % 5) {
+ case 0:
+ test_pack_unpack_c(buf);
+ break;
+ case 1:
+ test_pack_unpack_h(buf);
+ break;
+ case 2:
+ test_pack_unpack_u(buf);
+ break;
+ case 3:
+ test_pack_unpack_lu(buf);
+ break;
+ case 4:
+ test_pack_unpack_llu(buf);
+ break;
+ }
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ test_pack();
+ test_unpack();
+ test_pack_unpack();
+ return 0;
+}
diff --git a/test/test2/test.exp b/test/test2/test.exp
@@ -0,0 +1,256 @@
+0x0 0x1
+0x0 0x2
+0x0 0x4
+0x0 0x8
+0x0 0x10
+0x0 0x20
+0x0 0x40
+0x0 0x80
+0x0 0x100
+0x0 0x200
+0x0 0x400
+0x0 0x800
+0x0 0x1000
+0x0 0x2000
+0x0 0x4000
+0x0 0x8000
+0x0 0x10000
+0x0 0x20000
+0x0 0x40000
+0x0 0x80000
+0x0 0x100000
+0x0 0x200000
+0x0 0x400000
+0x0 0x800000
+0x0 0x1000000
+0x0 0x2000000
+0x0 0x4000000
+0x0 0x8000000
+0x0 0x10000000
+0x0 0x20000000
+0x0 0x40000000
+0x0 0x80000000
+0x0 0x100000000
+0x0 0x200000000
+0x0 0x400000000
+0x0 0x800000000
+0x0 0x1000000000
+0x0 0x2000000000
+0x0 0x4000000000
+0x0 0x8000000000
+0x0 0x10000000000
+0x0 0x20000000000
+0x0 0x40000000000
+0x0 0x80000000000
+0x0 0x100000000000
+0x0 0x200000000000
+0x0 0x400000000000
+0x0 0x800000000000
+0x0 0x1000000000000
+0x0 0x2000000000000
+0x0 0x4000000000000
+0x0 0x8000000000000
+0x0 0x10000000000000
+0x0 0x20000000000000
+0x0 0x40000000000000
+0x0 0x80000000000000
+0x0 0x100000000000000
+0x0 0x200000000000000
+0x0 0x400000000000000
+0x0 0x800000000000000
+0x0 0x1000000000000000
+0x0 0x2000000000000000
+0x0 0x4000000000000000
+0x0 0x8000000000000000
+0x1 0x0
+0x2 0x0
+0x4 0x0
+0x8 0x0
+0x10 0x0
+0x20 0x0
+0x40 0x0
+0x80 0x0
+0x100 0x0
+0x200 0x0
+0x400 0x0
+0x800 0x0
+0x1000 0x0
+0x2000 0x0
+0x4000 0x0
+0x8000 0x0
+0x10000 0x0
+0x20000 0x0
+0x40000 0x0
+0x80000 0x0
+0x100000 0x0
+0x200000 0x0
+0x400000 0x0
+0x800000 0x0
+0x1000000 0x0
+0x2000000 0x0
+0x4000000 0x0
+0x8000000 0x0
+0x10000000 0x0
+0x20000000 0x0
+0x40000000 0x0
+0x80000000 0x0
+0x100000000 0x0
+0x200000000 0x0
+0x400000000 0x0
+0x800000000 0x0
+0x1000000000 0x0
+0x2000000000 0x0
+0x4000000000 0x0
+0x8000000000 0x0
+0x10000000000 0x0
+0x20000000000 0x0
+0x40000000000 0x0
+0x80000000000 0x0
+0x100000000000 0x0
+0x200000000000 0x0
+0x400000000000 0x0
+0x800000000000 0x0
+0x1000000000000 0x0
+0x2000000000000 0x0
+0x4000000000000 0x0
+0x8000000000000 0x0
+0x10000000000000 0x0
+0x20000000000000 0x0
+0x40000000000000 0x0
+0x80000000000000 0x0
+0x100000000000000 0x0
+0x200000000000000 0x0
+0x400000000000000 0x0
+0x800000000000000 0x0
+0x1000000000000000 0x0
+0x2000000000000000 0x0
+0x4000000000000000 0x0
+0x8000000000000000 0x0
+0x0 0x1
+0x0 0x2
+0x0 0x4
+0x0 0x8
+0x0 0x10
+0x0 0x20
+0x0 0x40
+0x0 0x80
+0x0 0x100
+0x0 0x200
+0x0 0x400
+0x0 0x800
+0x0 0x1000
+0x0 0x2000
+0x0 0x4000
+0x0 0x8000
+0x0 0x10000
+0x0 0x20000
+0x0 0x40000
+0x0 0x80000
+0x0 0x100000
+0x0 0x200000
+0x0 0x400000
+0x0 0x800000
+0x0 0x1000000
+0x0 0x2000000
+0x0 0x4000000
+0x0 0x8000000
+0x0 0x10000000
+0x0 0x20000000
+0x0 0x40000000
+0x0 0x80000000
+0x0 0x100000000
+0x0 0x200000000
+0x0 0x400000000
+0x0 0x800000000
+0x0 0x1000000000
+0x0 0x2000000000
+0x0 0x4000000000
+0x0 0x8000000000
+0x0 0x10000000000
+0x0 0x20000000000
+0x0 0x40000000000
+0x0 0x80000000000
+0x0 0x100000000000
+0x0 0x200000000000
+0x0 0x400000000000
+0x0 0x800000000000
+0x0 0x1000000000000
+0x0 0x2000000000000
+0x0 0x4000000000000
+0x0 0x8000000000000
+0x0 0x10000000000000
+0x0 0x20000000000000
+0x0 0x40000000000000
+0x0 0x80000000000000
+0x0 0x100000000000000
+0x0 0x200000000000000
+0x0 0x400000000000000
+0x0 0x800000000000000
+0x0 0x1000000000000000
+0x0 0x2000000000000000
+0x0 0x4000000000000000
+0x0 0x8000000000000000
+0x1 0x0
+0x2 0x0
+0x4 0x0
+0x8 0x0
+0x10 0x0
+0x20 0x0
+0x40 0x0
+0x80 0x0
+0x100 0x0
+0x200 0x0
+0x400 0x0
+0x800 0x0
+0x1000 0x0
+0x2000 0x0
+0x4000 0x0
+0x8000 0x0
+0x10000 0x0
+0x20000 0x0
+0x40000 0x0
+0x80000 0x0
+0x100000 0x0
+0x200000 0x0
+0x400000 0x0
+0x800000 0x0
+0x1000000 0x0
+0x2000000 0x0
+0x4000000 0x0
+0x8000000 0x0
+0x10000000 0x0
+0x20000000 0x0
+0x40000000 0x0
+0x80000000 0x0
+0x100000000 0x0
+0x200000000 0x0
+0x400000000 0x0
+0x800000000 0x0
+0x1000000000 0x0
+0x2000000000 0x0
+0x4000000000 0x0
+0x8000000000 0x0
+0x10000000000 0x0
+0x20000000000 0x0
+0x40000000000 0x0
+0x80000000000 0x0
+0x100000000000 0x0
+0x200000000000 0x0
+0x400000000000 0x0
+0x800000000000 0x0
+0x1000000000000 0x0
+0x2000000000000 0x0
+0x4000000000000 0x0
+0x8000000000000 0x0
+0x10000000000000 0x0
+0x20000000000000 0x0
+0x40000000000000 0x0
+0x80000000000000 0x0
+0x100000000000000 0x0
+0x200000000000000 0x0
+0x400000000000000 0x0
+0x800000000000000 0x0
+0x1000000000000000 0x0
+0x2000000000000000 0x0
+0x4000000000000000 0x0
+0x8000000000000000 0x0
diff --git a/test/test2/test.sh b/test/test2/test.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+set -e
+
+tmp1=`mktemp`
+trap "rm -f $tmp1;exit 1" EXIT INT QUIT TERM
+
+$EMUCMD ./run > $tmp1
+diff -u $tmp1 test.exp
+rm $tmp1
+trap - EXIT