We need a Xvisor friendly firmware/bootloader for Virt-v8 guest which
will help us launch Guest OSes on Virt-v8 guest and also help us do
some testing of virtual CPU emulated by Xvisor ARM64.
This patch adds arm64 basic firmware for Virt-v8 Guest which is very
similar to arm32 basic firmware for VExpress-A15 Guest. This firmware
is capable of booting upstream arm64 linux kernel.
64 files changed, 13905 insertions(+)
diff --git a/tests/arm64/common/README b/tests/arm64/common/README
new file mode 100644
index 0000000..c6f8f0d
--- /dev/null
+++ b/tests/arm64/common/README
@@ -0,0 +1,9 @@
+ ARM64 common code
+
+This directory contains directories:
+
+ 1. busybox - Busybox based root filesystem for all ARM64 systems
+ 2. basic - Common code for the basic firmware
+
+Please follow the README under specific platform directory for detailed
+steps to configure, compile and run.
diff --git a/tests/arm64/common/basic/Makefile.inc b/tests/arm64/common/basic/Makefile.inc
new file mode 100644
index 0000000..c54e880
--- /dev/null
+++ b/tests/arm64/common/basic/Makefile.inc
@@ -0,0 +1,134 @@
+#/**
+# Copyright (c) 2013 Sukanto Ghosh.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# @file Makefile.inc
+# @brief common makefile to build basic firmware
+# */
+
+# Include top-level configuration file if present
+-include $(build_dir)/.config
+
+ifdef CROSS_COMPILE
+FW_CROSS_COMPILE=$(CROSS_COMPILE)
+else
+FW_CROSS_COMPILE=aarch64-none-linux-gnu-
+endif
+FW_CPPFLAGS=-I. -I$(common_dir) -DTEXT_START=$(board_text_start)
+FW_CFLAGS=$(FW_CPPFLAGS) -g -Wall -Werror -nostdlib -mgeneral-regs-only -mlittle-endian
+FW_ASFLAGS=$(FW_CPPFLAGS) -g -Wall -Werror -nostdlib -mgeneral-regs-only -mlittle-endian -D__ASSEMBLY__
+FW_LDFLAGS=$(FW_CFLAGS) -Wl,--build-id=none
+FW_AS=$(FW_CROSS_COMPILE)gcc
+FW_CC=$(FW_CROSS_COMPILE)gcc
+FW_CPP=$(FW_CROSS_COMPILE)cpp
+FW_OBJCOPY=$(FW_CROSS_COMPILE)objcopy
+
+FIRMWARE_OBJS=$(obj_dir)/arm_entry.o \
+ $(obj_dir)/arm_mmu.o
+
+FIRMWARE_OBJS+=$(board_objs)
+
+FIRMWARE_OBJS+=$(obj_dir)/arm_main.o \
+ $(obj_dir)/arm_heap.o \
+ $(obj_dir)/arm_irq.o \
+ $(obj_dir)/arm_stdio.o \
+ $(obj_dir)/arm_string.o \
+ $(obj_dir)/dhry_1.o \
+ $(obj_dir)/dhry_2.o \
+ $(obj_dir)/dhry_port.o \
+ $(obj_dir)/libfdt/fdt.o \
+ $(obj_dir)/libfdt/fdt_ro.o \
+ $(obj_dir)/libfdt/fdt_rw.o \
+ $(obj_dir)/libfdt/fdt_strerror.o \
+ $(obj_dir)/libfdt/fdt_support.o \
+ $(obj_dir)/libfdt/fdt_sw.o \
+ $(obj_dir)/libfdt/fdt_wip.o
+
+FIRMWARE_CPPFLAGS=-DFIRMWARE_BOOT
+FIRMWARE_CFLAGS=$(FIRMWARE_CPPFLAGS)
+FIRMWARE_ASFLAGS=$(FIRMWARE_CPPFLAGS)
+FIRMWARE_LINK_SCRIPT=$(obj_dir)/firmware.lnk
+FIRMWARE_LDFLAGS=-Wl,-T$(FIRMWARE_LINK_SCRIPT) $(FIRMWARE_CPPFLAGS)
+
+FIRMWARE_COMMON_DEPS=$(common_dir)/arm_asm_macro.h \
+ $(common_dir)/arm_math.h \
+ $(common_dir)/arm_defines.h \
+ $(common_dir)/arm_types.h \
+ $(common_dir)/arm_board.h \
+ $(common_dir)/arm_heap.h \
+ $(common_dir)/arm_inline_asm.h \
+ $(common_dir)/arm_io.h \
+ $(common_dir)/arm_irq.h \
+ $(common_dir)/arm_mmu.h \
+ $(common_dir)/arm_stdio.h \
+ $(common_dir)/arm_string.h \
+ $(common_dir)/libfdt/fdt.h \
+ $(common_dir)/libfdt/fdt_support.h \
+ $(common_dir)/libfdt/libfdt.h \
+ $(common_dir)/libfdt/libfdt_env.h \
+ $(common_dir)/libfdt/libfdt_internal.h
+
+FIRMWARE_TARGETS = $(obj_dir)/firmware.bin
+
+.PHONY: all
+all: $(FIRMWARE_TARGETS)
+
+$(obj_dir)/firmware.bin: $(obj_dir)/firmware.elf
+ @mkdir -p `dirname $@`
+ @echo " (OBJCOPY) $(subst $(obj_dir)/,,$@)"
+ @$(FW_OBJCOPY) -O binary $< $@
+
+$(obj_dir)/firmware.elf: $(FIRMWARE_OBJS) $(FIRMWARE_LINK_SCRIPT)
+ @mkdir -p `dirname $@`
+ @echo " (LD) $(subst $(obj_dir)/,,$@)"
+ @$(FW_CC) $(FIRMWARE_OBJS) $(FW_LDFLAGS) $(FIRMWARE_LDFLAGS) -o $@
+
+$(obj_dir)/%.lnk: $(common_dir)/%.ld
+ @mkdir -p `dirname $@`
+ @echo " (CPP) $(subst $(obj_dir)/,,$@)"
+ @$(FW_CPP) $(FW_CPPFLAGS) $(FIRMWARE_CPPFLAGS) $< | grep -v "\#" > $@
+
+$(obj_dir)/%.o: %.c $(FIRMWARE_COMMON_DEPS)
+ @mkdir -p `dirname $@`
+ @echo " (CC) $(subst $(obj_dir)/,,$@)"
+ @$(FW_CC) $(FW_CFLAGS) $(FIRMWARE_CFLAGS) -c $< -o $@
+
+$(obj_dir)/%.o: $(common_dir)/%.c $(FIRMWARE_COMMON_DEPS)
+ @mkdir -p `dirname $@`
+ @echo " (CC) $(subst $(obj_dir)/,,$@)"
+ @$(FW_CC) $(FW_CFLAGS) $(FIRMWARE_CFLAGS) -c $< -o $@
+
+$(obj_dir)/%.o: %.S $(FIRMWARE_COMMON_DEPS)
+ @mkdir -p `dirname $@`
+ @echo " (AS) $(subst $(obj_dir)/,,$@)"
+ @$(FW_AS) $(FW_ASFLAGS) $(FIRMWARE_ASFLAGS) -c $< -o $@
+
+$(obj_dir)/%.o: $(common_dir)/%.S $(FIRMWARE_COMMON_DEPS)
+ @mkdir -p `dirname $@`
+ @echo " (AS) $(subst $(obj_dir)/,,$@)"
+ @$(FW_AS) $(FW_ASFLAGS) $(FIRMWARE_ASFLAGS) -c $< -o $@
+
+.PHONY: clean
+clean:
+ @echo " (RM) firmware.elf*"
+ @rm -f $(obj_dir)/firmware.elf*
+ @echo " (RM) firmware.bin*"
+ @rm -f $(obj_dir)/firmware.bin*
+ @echo " (RM) $(obj_dir)"
+ @rm -rf $(obj_dir)
+
diff --git a/tests/arm64/common/basic/README b/tests/arm64/common/basic/README
new file mode 100644
index 0000000..70e5ee4
--- /dev/null
+++ b/tests/arm64/common/basic/README
@@ -0,0 +1,5 @@
+ Common basic firmware code
+
+This directory contains souce code files that are common to all boards and
+arm64 processors.
+
diff --git a/tests/arm64/common/basic/arm_asm_macro.h b/tests/arm64/common/basic/arm_asm_macro.h
new file mode 100644
index 0000000..4ab7955
--- /dev/null
+++ b/tests/arm64/common/basic/arm_asm_macro.h
@@ -0,0 +1,139 @@
+/**
+ * Copyright (c) 2010 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_asm_macros.h
+ * @brief common assembly macros for ARM test code
+ */
+#ifndef __ARM_ASM_MACRO_H__
+#define __ARM_ASM_MACRO_H__
+
+#include <arm_defines.h>
+
+#ifdef __ASSEMBLY__
+
+/*
+ * Register aliases.
+ */
+lr .req x30 /* link register */
+
+#define ENTRY(name) \
+ .globl name; \
+ .align 4; \
+ name:
+
+#define END(name) \
+ .size name, .-name
+ mrs x22, elr_el1
+ mrs x23, spsr_el1
+ stp lr, x21, [sp, #0xF0]
+ stp x22, x23, [sp, #0x100]
+ /*
+ * Registers that may be useful after this macro is invoked:
+ *
+ * x21 - aborted SP
+ * x22 - aborted PC
+ * x23 - aborted PSTATE
+ */
+.endm
+
+/* Call C function to handle exception */
+.macro CALL_EXCEPTION_CFUNC cfunc
+ mov x0, sp
+ bl \cfunc
+.endm
+
+/* Pull registers from stack */
+.macro PULL_REGS
+ ldp x21, x22, [sp, #0x100] /* load ELR, SPSR */
+ msr elr_el1, x21
+ msr spsr_el1, x22
+ pop x0, x1
+ pop x2, x3
+ pop x4, x5
+ pop x6, x7
+ pop x8, x9
+ pop x10, x11
+ pop x12, x13
+ pop x14, x15
+ pop x16, x17
+ pop x18, x19
+ pop x20, x21
+ pop x22, x23
+ pop x24, x25
+ pop x26, x27
+ pop x28, x29
+ msr tpidr_el1, x24
+ ldp lr, x24, [sp]
+ mov sp, x24
+ mrs x24, tpidr_el1
+ eret
+.endm
+
+/*
+ * Exception vectors.
+ */
+.macro ventry label
+ .align 7
+ b \label
+.endm
+
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/tests/arm64/common/basic/arm_board.h b/tests/arm64/common/basic/arm_board.h
new file mode 100644
index 0000000..b0dac5f
--- /dev/null
+++ b/tests/arm64/common/basic/arm_board.h
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2012 Jean-Christophe Dubois.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_board.h
+ * @author Jean-Christophe Dubois (
j...@tribudubois.net)
+ * @brief ARM Platform misc functions Header
+ */
+#ifndef _ARM_BOARD_H__
+#define _ARM_BOARD_H__
+
+#include <arm_types.h>
+
+void arm_board_reset(void);
+void arm_board_init(void);
+char *arm_board_name(void);
+physical_addr_t arm_board_ram_start(void);
+physical_size_t arm_board_ram_size(void);
+physical_addr_t arm_board_flash_addr(void);
+u32 arm_board_linux_machine_type(void);
+void arm_board_linux_default_cmdline(char *cmdline, u32 cmdline_sz);
+
+u32 arm_board_iosection_count(void);
+physical_addr_t arm_board_iosection_addr(int num);
+
+u32 arm_board_pic_nr_irqs(void);
+int arm_board_pic_init(void);
+u32 arm_board_pic_active_irq(void);
+int arm_board_pic_ack_irq(u32 irq);
+int arm_board_pic_eoi_irq(u32 irq);
+int arm_board_pic_mask(u32 irq);
+int arm_board_pic_unmask(u32 irq);
+
+void arm_board_timer_enable(void);
+void arm_board_timer_disable(void);
+u64 arm_board_timer_irqcount(void);
+u64 arm_board_timer_irqdelay(void);
+u64 arm_board_timer_timestamp(void);
+void arm_board_timer_change_period(u32 usecs);
+int arm_board_timer_init(u32 usecs);
+
+int arm_board_serial_init(void);
+void arm_board_serial_putc(char ch);
+char arm_board_serial_getc(void);
+
+#endif
diff --git a/tests/arm64/common/basic/arm_defines.h b/tests/arm64/common/basic/arm_defines.h
new file mode 100644
index 0000000..4084e0a
--- /dev/null
+++ b/tests/arm64/common/basic/arm_defines.h
@@ -0,0 +1,312 @@
+/**
+ * Copyright (c) 2010 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_defines.h
+ * @brief register related macros & defines for ARM test code
+ */
+#ifndef __ARM_DEFINES_H__
+#define __ARM_DEFINES_H__
+
+/* Interrupt or Exception related macros & defines */
+#define EXC_SVC_SYNC_SP0 0
+#define EXC_SVC_IRQ_SP0 1
+#define EXC_SVC_FIQ_SP0 2
+#define EXC_SVC_SERROR_SP0 3
+#define EXC_SVC_SYNC_SPx 4
+#define EXC_SVC_IRQ_SPx 5
+#define EXC_SVC_FIQ_SPx 6
+#define EXC_SVC_SERROR_SPx 7
+#define EXC_USR_SYNC_A64 8
+#define EXC_USR_IRQ_A64 9
+#define EXC_USR_FIQ_A64 10
+#define EXC_USR_SERROR_A64 11
+#define EXC_USR_SYNC_A32 12
+#define EXC_USR_IRQ_A32 13
+#define EXC_USR_FIQ_A32 14
+#define EXC_USR_SERROR_A32 15
+
+/* PSR related macros & defines */
+#define PSR_EL_MASK 0x0000000C
+#define PSR_EL_0 0x00000000
+#define PSR_EL_1 0x00000004
+#define PSR_EL_2 0x00000008
+#define PSR_EL_3 0x0000000C
+#define PSR_MODE_MASK 0x0000000f
+#define PSR_MODE_EL0t 0x00000000
+#define PSR_MODE_EL1t 0x00000004
+#define PSR_MODE_EL1h 0x00000005
+#define PSR_MODE_EL2t 0x00000008
+#define PSR_MODE_EL2h 0x00000009
+#define PSR_MODE_EL3t 0x0000000c
+#define PSR_MODE_EL3h 0x0000000d
+
+#define PSR_FIQ_DISABLED (1 << 6)
+#define PSR_IRQ_DISABLED (1 << 7)
+#define PSR_ASYNC_ABORT_DISABLED (1 << 8)
+#define PSR_BE_ENABLED (1 << 9)
+
+#define PSR_COND_OVERFLOW (1 << 28)
+#define PSR_COND_CARRY (1 << 29)
+#define PSR_COND_ZERO (1 << 30)
+#define PSR_COND_NEGATIVE (1 << 31)
+
+/* SCTLR related macros & defines */
+#define SCTLR_TE_MASK 0x40000000
+#define SCTLR_AFE_MASK 0x20000000
+#define SCTLR_TRE_MASK 0x10000000
+#define SCTLR_NFI_MASK 0x08000000
+#define SCTLR_EE_MASK 0x02000000
+#define SCTLR_VE_MASK 0x01000000
+#define SCTLR_U_MASK 0x00400000
+#define SCTLR_FI_MASK 0x00200000
+#define SCTLR_HA_MASK 0x00020000
+#define SCTLR_RR_MASK 0x00004000
+#define SCTLR_V_MASK 0x00002000
+#define SCTLR_I_MASK 0x00001000
+#define SCTLR_Z_MASK 0x00000800
+#define SCTLR_SW_MASK 0x00000400
+#define SCTLR_B_MASK 0x00000080
+#define SCTLR_C_MASK 0x00000004
+#define SCTLR_A_MASK 0x00000002
+#define SCTLR_M_MASK 0x00000001
+
+/* TCR_EL1 */
+#define TCR_INITVAL 0x80800000
+#define TCR_TBI_MASK 0x00100000
+#define TCR_TBI_SHIFT 20
+#define TCR_PS_MASK 0x00070000
+#define TCR_PS_SHIFT 16
+#define TCR_TG0_MASK 0x00004000
+#define TCR_TG0_SHIFT 14
+#define TCR_SH0_MASK 0x00003000
+#define TCR_SH0_SHIFT 12
+#define TCR_ORGN0_MASK 0x00000C00
+#define TCR_ORGN0_SHIFT 10
+#define TCR_IRGN0_MASK 0x00000300
+#define TCR_IRGN0_SHIFT 8
+#define TCR_T0SZ_MASK 0x0000003f
+#define TCR_T0SZ_SHIFT 0
+
+/* MAIR_EL1 encodings */
+#define AINDEX_SO 0
+#define AINDEX_NORMAL_WT 1
+#define AINDEX_NORMAL_WB 2
+#define AINDEX_NORMAL_UC 3
+#define MAIR_INITVAL 0x0000000044FFBB00
+
+/* Translation table related macros & defines */
+#define TTBL_INITIAL_TABLE_COUNT 8
+#define TTBL_TABLE_SIZE 0x00001000
+#define TTBL_TABLE_SIZE_SHIFT 12
+#define TTBL_TABLE_ENTCNT 512
+#define TTBL_TABLE_ENTSZ 8
+#define TTBL_STAGE1 1
+#define TTBL_STAGE2 2
+#define TTBL_FIRST_LEVEL 1
+#define TTBL_LEVEL1 1
+#define TTBL_LEVEL2 2
+#define TTBL_LEVEL3 3
+#define TTBL_LAST_LEVEL 3
+/* L1 index Bit[39:30] */
+#define TTBL_L1_INDEX_MASK 0x000000FFC0000000ULL
+#define TTBL_L1_INDEX_SHIFT 30
+#define TTBL_L1_BLOCK_SIZE 0x0000000040000000ULL
+#define TTBL_L1_MAP_MASK (~(TTBL_L1_BLOCK_SIZE - 1))
+/* L2 index Bit[29:21] */
+#define TTBL_L2_INDEX_MASK 0x000000003FE00000ULL
+#define TTBL_L2_INDEX_SHIFT 21
+#define TTBL_L2_BLOCK_SIZE 0x0000000000200000ULL
+#define TTBL_L2_MAP_MASK (~(TTBL_L2_BLOCK_SIZE - 1))
+/* L3 index Bit[20:12] */
+#define TTBL_L3_INDEX_MASK 0x00000000001FF000ULL
+#define TTBL_L3_INDEX_SHIFT 12
+#define TTBL_L3_BLOCK_SIZE 0x0000000000001000ULL
+#define TTBL_L3_MAP_MASK (~(TTBL_L3_BLOCK_SIZE - 1))
+#define TTBL_UPPER_MASK 0xFFF0000000000000ULL
+#define TTBL_UPPER_SHIFT 52
+#define TTBL_OUTADDR_MASK 0x000000FFFFFFF000ULL
+#define TTBL_OUTADDR_SHIFT 12
+#define TTBL_AP_SRW_U 0x0
+#define TTBL_AP_S_URW 0x1
+#define TTBL_AP_SR_U 0x2
+#define TTBL_AP_S_UR 0x3
+#define TTBL_HAP_NOACCESS 0x0
+#define TTBL_HAP_READONLY 0x1
+#define TTBL_HAP_WRITEONLY 0x2
+#define TTBL_HAP_READWRITE 0x3
+#define TTBL_LOWER_MASK 0x0000000000000FFCULL
+#define TTBL_LOWER_SHIFT 2
+#define TTBL_TABLE_MASK 0x0000000000000002ULL
+#define TTBL_TABLE_SHIFT 1
+#define TTBL_VALID_MASK 0x0000000000000001ULL
+#define TTBL_VALID_SHIFT 0
+
+/* TTBL Stage1 Table Attributes */
+#define TTBL_STAGE1_TABLE_NS_MASK 0x8000000000000000ULL
+#define TTBL_STAGE1_TABLE_NS_SHIFT 63
+#define TTBL_STAGE1_TABLE_AP_MASK 0x6000000000000000ULL
+#define TTBL_STAGE1_TABLE_AP_SHIFT 61
+#define TTBL_STAGE1_TABLE_XN_MASK 0x1000000000000000ULL
+#define TTBL_STAGE1_TABLE_XN_SHIFT 60
+#define TTBL_STAGE1_TABLE_PXN_MASK 0x0800000000000000ULL
+#define TTBL_STAGE1_TABLE_PXN_SHIFT 59
+
+/* TTBL Stage1 Block Upper Attributes */
+#define TTBL_STAGE1_UPPER_XN_MASK 0x0040000000000000ULL
+#define TTBL_STAGE1_UPPER_XN_SHIFT 54
+#define TTBL_STAGE1_UPPER_PXN_MASK 0x0020000000000000ULL
+#define TTBL_STAGE1_UPPER_PXN_SHIFT 53
+#define TTBL_STAGE1_UPPER_CONT_MASK 0x0010000000000000ULL
+#define TTBL_STAGE1_UPPER_CONT_SHIFT 52
+
+/* TTBL Stage1 Block Lower Attributes */
+#define TTBL_STAGE1_LOWER_NG_MASK 0x0000000000000800ULL
+#define TTBL_STAGE1_LOWER_NG_SHIFT 11
+#define TTBL_STAGE1_LOWER_AF_MASK 0x0000000000000400ULL
+#define TTBL_STAGE1_LOWER_AF_SHIFT 10
+#define TTBL_STAGE1_LOWER_SH_MASK 0x0000000000000300ULL
+#define TTBL_STAGE1_LOWER_SH_SHIFT 8
+#define TTBL_STAGE1_LOWER_AP_MASK 0x00000000000000C0ULL
+#define TTBL_STAGE1_LOWER_AP_SHIFT 6
+#define TTBL_STAGE1_LOWER_NS_MASK 0x0000000000000020ULL
+#define TTBL_STAGE1_LOWER_NS_SHIFT 5
+#define TTBL_STAGE1_LOWER_AINDEX_MASK 0x000000000000001CULL
+#define TTBL_STAGE1_LOWER_AINDEX_SHIFT 2
+
+/* ESR_EL1 */
+/* WFI/WFE ISS Encodings */
+#define ISS_WFI_WFE_TRAPPED_MASK 0x00080000
+#define ISS_WFI_WFE_TRAPPED_SHIFT 19
+
+
+#endif
diff --git a/tests/arm64/common/basic/arm_entry.S b/tests/arm64/common/basic/arm_entry.S
new file mode 100644
index 0000000..c1a988d
--- /dev/null
+++ b/tests/arm64/common/basic/arm_entry.S
@@ -0,0 +1,323 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_entry.S
+ * @brief Entry point code for basic firmware
+ */
+
+#include <arm_asm_macro.h>
+#include <gic_config.h>
+#include <arm_plat.h>
+
+ /*
+ * Basic firmware could be loaded any where in memory.
+ * The _start function ensures that it exectues from intended
+ * base address provided at compile time.
+ */
+ .section .text, "ax", %progbits
+ .globl _start
+_start:
+ /*
+ * x4 -> load start
+ * x5 -> load end
+ * x6 -> execution start
+ * x7 -> execution end
+ * x8 -> code size
+ */
+ adr x4, . /* x4 <- pc */
+ /* Disable IRQ & FIQ */
+ msr daifset, #3
+ ldr x6, __reloc_region_start
+ ldr x7, __reloc_region_end
+ sub x8, x7, x6
+ add x5, x4, x8
+
+ /* If not-running at EL1 then hang */
+ mrs x0, CurrentEL
+ cmp x0, #PSR_MODE_EL1t
+ ccmp x0, #PSR_MODE_EL1h, #0x4, ne
+
b.ne _start_hang
+
+ /* Set GIC priority mask bit [7] = 1 */
+ ldr x0, __gic_cpu_base /* CPU GIC base */
+ mov x1, #0x1
+ str w1, [x0] /* GIC CPU CTRL */
+ mov x1, #0xFF
+ str w1, [x0, #0x4] /* GIC CPU PMR */
+
+ /* Skip secondary spin for primary core */
+ mrs x0, mpidr_el1
+ ands x0, x0, #15 /* CPU number */
+ cmp x0, #0
+ b.eq primary_cpu_boot
+
+ /* Secondary spin loop */
+ ldr x0, __jump_addr
+ str xzr, [x0]
+secondary_cpu_spin:
+ ldr x1, [x0]
+ cbnz x1, secondary_cpu_jump
+ wfe
+ b secondary_cpu_spin
+secondary_cpu_jump:
+ br x1
+
+ .align 3
+__gic_cpu_base:
+ .dword GIC_CPU_BASE
+
+ .align 3
+ .global __jump_addr
+__jump_addr:
+ .dword ARM_PLAT_SPIN_ADDR
+
+ /* Primary core boot-up sequence */
+primary_cpu_boot:
+ /* Check if relocation required */
+ cmp x4, x6
+ b.eq _relocate_end
+
+ /*
+ * We need to clear the A bit in sctlr_el1
+ * for the relocate routine to work properly
+ */
+ mrs x3, sctlr_el1
+ ldr x2, __sctlr_mmu_clear
+ and x3, x3, x2
+ /* We also enable I/D caching */
+ ldr x2, __sctlr_mmu_val
+ orr x3, x3, x2
+ msr sctlr_el1, x3
+ dsb sy
+ isb
+
+ mov x0, x6 /* destination */
+ mov x1, x4 /* source */
+ mov x2, x8 /* byte count */
+ /* TODO: Handle overlaps */
+_relocate:
+ subs x2, x2, #8
+ b.mi 2f
+1: ldr x3, [x1], #8
+ subs x2, x2, #8
+ str x3, [x0], #8
+
b.pl 1b
+2: adds x2, x2, #4
+ b.mi 3f
+ ldr w3, [x1], #4
+ sub x2, x2, #4
+ str w3, [x0], #4
+3: adds x2, x2, #2
+ b.mi 4f
+ ldrh w3, [x1], #2
+ sub x2, x2, #2
+ strh w3, [x0], #2
+4: adds x2, x2, #1
+ b.mi _relocate_end
+ ldrb w3, [x1]
+ strb w3, [x0]
+_relocate_end:
+
+ ldr x0, __relocated
+ br x0
+
+_relocated:
+
+ /* Zero out bss & heap */
+ ldr x0, __zero_region_start
+ ldr x1, __zero_region_end
+1: subs x2, x1, x0
+ b.le 2f
+ str xzr, [x0]
+ add x0, x0, 8
+ b 1b
+2:
+ /* Set exception vectors */
+ adr x0, vectors
+ msr vbar_el1, x0
+ /* Set EL1 stack-pointer */
+ ldr x0, __el1_stack
+ mov sp, x0
+ /* Set EL0 stack-pointer */
+ ldr x0, __el0_stack
+ msr sp_el0, x0
+
+ bl arm_init
+ bl arm_main
+
+_start_hang:
+ b .
+
+ .align 3
+__relocated:
+ .dword _relocated
+
+ .globl _switch_to_user_mode
+_switch_to_user_mode:
+ msr tpidr_el1, x0
+ mov x0, #(PSR_FIQ_DISABLED | PSR_IRQ_DISABLED |\
+ PSR_ASYNC_ABORT_DISABLED | PSR_MODE_EL0t)
+ msr spsr_el1, x0
+ mrs x0, tpidr_el1
+ msr elr_el1, lr
+ eret
+
+ .align 3
+__sctlr_mmu_clear:
+ .dword ~(SCTLR_A_MASK)
+__sctlr_mmu_val:
+ .dword (SCTLR_C_MASK | SCTLR_I_MASK)
+__reloc_region_start:
+ .dword _reloc_region_start
+__reloc_region_end:
+ .dword _reloc_region_end
+__zero_region_start:
+ .dword _zero_region_start
+__zero_region_end:
+ .dword _zero_region_end
+
+ /*
+ * Stacks.
+ */
+__el0_stack:
+ .dword _usr_stack_end
+__el1_stack:
+ .dword _svc_stack_end
+
+
+ .align 11
+ENTRY(vectors)
+ ventry svc_sync_invalid /* Synchronous EL1t */
+ ventry svc_irq_invalid /* IRQ EL1t */
+ ventry svc_fiq_invalid /* FIQ EL1t */
+ ventry svc_error_invalid /* Error EL1t */
+
+ ventry svc_sync /* Synchronous EL1h */
+ ventry svc_irq /* IRQ EL1h */
+ ventry svc_fiq_invalid /* FIQ EL1h */
+ ventry svc_error_invalid /* Error EL1h */
+
+ ventry usr_sync_a64 /* Synchronous 64-bit EL0 */
+ ventry usr_irq_a64 /* IRQ 64-bit EL0 */
+ ventry usr_fiq_a64 /* FIQ 64-bit EL0 */
+ ventry usr_error_a64 /* Error 64-bit EL0 */
+
+ ventry usr_sync_a32 /* Synchronous 32-bit EL0 */
+ ventry usr_irq_a32 /* IRQ 32-bit EL0 */
+ ventry usr_fiq_a32 /* FIQ 32-bit EL0 */
+ ventry usr_error_a32 /* Error 32-bit EL0 */
+END(vectors)
+
+EXCEPTION_HANDLER svc_sync_invalid
+ PUSH_REGS
+ mov x1, EXC_SVC_SYNC_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_irq_invalid
+ PUSH_REGS
+ mov x1, EXC_SVC_IRQ_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_fiq_invalid
+ PUSH_REGS
+ mov x1, EXC_SVC_FIQ_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_error_invalid
+ PUSH_REGS
+ mov x1, EXC_SVC_SERROR_SP0
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_sync
+ PUSH_REGS
+ mov x1, EXC_SVC_SYNC_SPx
+ CALL_EXCEPTION_CFUNC do_sync
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_irq
+ PUSH_REGS
+ mov x1, EXC_SVC_IRQ_SPx
+ CALL_EXCEPTION_CFUNC do_irq
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_fiq
+ PUSH_REGS
+ mov x1, EXC_SVC_FIQ_SPx
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER svc_error
+ PUSH_REGS
+ mov x1, EXC_SVC_SERROR_SPx
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_sync_a64
+ PUSH_REGS
+ mov x1, EXC_USR_SYNC_A64
+ CALL_EXCEPTION_CFUNC do_sync
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_irq_a64
+ PUSH_REGS
+ mov x1, EXC_USR_IRQ_A64
+ CALL_EXCEPTION_CFUNC do_irq
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_fiq_a64
+ PUSH_REGS
+ mov x1, EXC_USR_FIQ_A64
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_error_a64
+ PUSH_REGS
+ mov x1, EXC_USR_SERROR_A64
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_sync_a32
+ PUSH_REGS
+ mov x1, EXC_USR_SYNC_A32
+ CALL_EXCEPTION_CFUNC do_sync
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_irq_a32
+ PUSH_REGS
+ mov x1, EXC_USR_IRQ_A32
+ CALL_EXCEPTION_CFUNC do_irq
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_fiq_a32
+ PUSH_REGS
+ mov x1, EXC_USR_FIQ_A32
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+EXCEPTION_HANDLER usr_error_a32
+ PUSH_REGS
+ mov x1, EXC_USR_SERROR_A32
+ CALL_EXCEPTION_CFUNC do_bad_mode
+ PULL_REGS
+
+
diff --git a/tests/arm64/common/basic/arm_heap.c b/tests/arm64/common/basic/arm_heap.c
new file mode 100644
index 0000000..03a4989
--- /dev/null
+++ b/tests/arm64/common/basic/arm_heap.c
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_heap.c
+ * @brief source file for heap managment
+ */
+
+#include <arm_heap.h>
+
+static void * heap_curr;
+extern u8 _heap_start;
+
+void * arm_malloc(size_t size)
+{
+ void * retval;
+ /* Make size 8B aligned */
+ if (size & 0x7)
+ size = ((size / 8) + 1) * 8;
+ retval = heap_curr;
+ heap_curr += size;
+ return retval;
+}
+
+void arm_heap_init(void)
+{
+ heap_curr = &_heap_start;
+}
+
diff --git a/tests/arm64/common/basic/arm_heap.h b/tests/arm64/common/basic/arm_heap.h
new file mode 100644
index 0000000..4c3565b
--- /dev/null
+++ b/tests/arm64/common/basic/arm_heap.h
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_heap.h
+ * @brief Header file for heap managment
+ */
+
+#ifndef __ARM_HEAP_H_
+#define __ARM_HEAP_H_
+
+#include <arm_types.h>
+
+void * arm_malloc(size_t size);
+void arm_heap_init(void);
+
+#endif /* __ARM_HEAP_H_ */
diff --git a/tests/arm64/common/basic/arm_inline_asm.h b/tests/arm64/common/basic/arm_inline_asm.h
new file mode 100644
index 0000000..5be7b32
--- /dev/null
+++ b/tests/arm64/common/basic/arm_inline_asm.h
@@ -0,0 +1,118 @@
+/**
+ * Copyright (c) 2012 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_inline_asm.h
+ * @brief Frequently required inline assembly macros
+ */
+#ifndef __ARM_INLINE_ASM_H__
+#define __ARM_INLINE_ASM_H__
+
+#include <arm_types.h>
+#define msr_sync(spr, val) asm volatile("msr " #spr ", %0\n\tdsb sy\n\tisb" ::"r"(val));
+
+#define dsb() asm volatile("dsb sy":::"memory","cc");
+
+#define isb() asm volatile("isb":::"memory","cc");
+
+
+/* TLB maintainence */
+
+#define inv_tlb_all() asm volatile("tlbi vmalle1is\n\tdsb sy\n\tisb\n\t"::: "memory", "cc");
+
+#define inv_tlb_va(va) asm volatile("tlbi vaae1is, %0\n\tdsb sy\n\tisb\n\t" \
+ :: "r" ((va >> 12)) : "memory", "cc")
+
+
+/* VA to PA Address Translation */
+
+#define VA2PA_STAGE1 "s1"
+#define VA2PA_STAGE12 "s12"
+#define VA2PA_EL0 "e0"
+#define VA2PA_EL1 "e1"
+#define VA2PA_EL2 "e2"
+#define VA2PA_EL3 "e3"
+#define VA2PA_RD "r"
+#define VA2PA_WR "w"
+#define va2pa_at(stage, el, rw, va) asm volatile( \
+ "at " stage el rw ", %0" \
+ : : "r"(va) : "memory", "cc");
+
+
+/* Features */
+#define cpu_supports_thumbee() ({ u64 pfr0; asm volatile("mrs %0, id_pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_THUMBEE_MASK); })
+
+#define cpu_supports_thumb() ({ u64 pfr0; asm volatile("mrs %0, id_pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_THUMBEE_MASK); })
+
+#define cpu_supports_thumb2() ({ u64 pfr0; asm volatile("mrs %0, id_pfr0_el1": "=r"(pfr0)); \
+ ((pfr0 & ID_PFR0_THUMB_MASK) == ID_PFR0_THUMB2_MASK); })
+
+#define cpu_supports_jazelle() ({ u64 pfr0; asm volatile("mrs %0, id_pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_JAZELLE_MASK); })
+
+#define cpu_supports_arm() ({ u64 pfr0; asm volatile("mrs %0, id_pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_PFR0_ARM_MASK); })
+
+#define cpu_supports_asimd() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ ((pfr0 & ID_AA64PFR0_ASIMD_MASK) == 0); })
+
+#define cpu_supports_fpu() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ ((pfr0 & ID_AA64PFR0_FPU_MASK) == 0); })
+
+#define cpu_supports_el0_a32() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL0_A32); })
+
+#define cpu_supports_el1_a32() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL1_A32);})
+
+#define cpu_supports_el2_a32() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL2_A32); })
+
+#define cpu_supports_el3_a32() ({ u64 pfr0; asm volatile("mrs %0, id_aa64pfr0_el1": "=r"(pfr0)); \
+ (pfr0 & ID_AA64PFR0_EL3_A32); })
+
+#endif
diff --git a/tests/arm64/common/basic/arm_io.h b/tests/arm64/common/basic/arm_io.h
new file mode 100644
index 0000000..05049aa
--- /dev/null
+++ b/tests/arm64/common/basic/arm_io.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_io.h
+ * @brief Header file for common I/O functions
+ */
+
+#ifndef __ARM_IO_H_
+#define __ARM_IO_H_
+
+#include <arm_types.h>
+
+static inline u32 arm_readl(void *addr)
+{
+ return *((u32 *)addr);
+}
+
+static inline void arm_writel(u32 data, void *addr)
+{
+ *((u32 *)addr) = data;
+}
+
+#endif /* __ARM_IO_H_ */
diff --git a/tests/arm64/common/basic/arm_irq.c b/tests/arm64/common/basic/arm_irq.c
new file mode 100644
index 0000000..2e450f1
--- /dev/null
+++ b/tests/arm64/common/basic/arm_irq.c
@@ -0,0 +1,122 @@
+/**
+ * Copyright (c) 2010 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_irq.c
+ * @brief source code for handling ARM test code interrupts
+ */
+
+#include <arm_board.h>
+#include <arm_mmu.h>
+#include <arm_irq.h>
+#include <arm_stdio.h>
+
+#define MAX_NR_IRQS 1024
+
+arm_irq_handler_t irq_hndls[MAX_NR_IRQS];
+
+#define PIC_NR_IRQS ((arm_board_pic_nr_irqs() < MAX_NR_IRQS) ? \
+ arm_board_pic_nr_irqs() : MAX_NR_IRQS)
+
+void do_bad_mode(struct pt_regs *regs)
+{
+ arm_puts("Bad exception\n");
+ while(1);
+}
+
+void do_sync(struct pt_regs *regs)
+{
+ arm_sync_abort(regs);
+}
+
+void do_irq(struct pt_regs *regs)
+{
+ int rc = 0;
+ int irq = arm_board_pic_active_irq();
+
+ if (-1 < irq) {
+ rc = arm_board_pic_ack_irq(irq);
+ if (rc) {
+ while (1);
+ }
+ if (irq_hndls[irq]) {
+ rc = irq_hndls[irq](irq, regs);
+ if (rc) {
+ while (1);
+ }
+ }
+ rc = arm_board_pic_eoi_irq(irq);
+ if (rc) {
+ while (1);
+ }
+ }
+}
+
+void do_fiq(struct pt_regs *regs)
+{
+}
+
+void arm_irq_setup(void)
+{
+ int vec;
+
+ /*
+ * Reset irq handlers
+ */
+ for (vec = 0; vec < PIC_NR_IRQS; vec++) {
+ irq_hndls[vec] = NULL;
+ }
+
+ /*
+ * Initialize board PIC
+ */
+ vec = arm_board_pic_init();
+ if (vec) {
+ while (1);
+ }
+}
+
+void arm_irq_register(u32 irq, arm_irq_handler_t hndl)
+{
+ int rc = 0;
+ if (irq < PIC_NR_IRQS) {
+ irq_hndls[irq] = hndl;
+ if (irq_hndls[irq]) {
+ rc = arm_board_pic_unmask(irq);
+ if (rc) {
+ while (1);
+ }
+ }
+ }
+}
+
+void arm_irq_enable(void)
+{
+ asm volatile("msr daifclr, #2":::"memory");
+}
+
+void arm_irq_disable(void)
+{
+ asm volatile("msr daifset, #2":::"memory");
+}
+
+void arm_irq_wfi(void)
+{
+ __asm ("wfi\n");
+}
+
diff --git a/tests/arm64/common/basic/arm_irq.h b/tests/arm64/common/basic/arm_irq.h
new file mode 100644
index 0000000..26580eb
--- /dev/null
+++ b/tests/arm64/common/basic/arm_irq.h
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2010 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_irq.h
+ * @brief header file for ARM interrupts
+ */
+#ifndef _ARM_IRQ_H__
+#define _ARM_IRQ_H__
+
+#include <arm_types.h>
+
+typedef int (*arm_irq_handler_t) (u32 irq_no, struct pt_regs * regs);
+
+#define CPU_IRQ_NR 8
+
+/** IRQ Numbers */
+#define ARM_RESET_IRQ 0
+#define ARM_UNDEF_INST_IRQ 1
+#define ARM_SOFT_IRQ 2
+#define ARM_PREFETCH_ABORT_IRQ 3
+#define ARM_DATA_ABORT_IRQ 4
+#define ARM_NOT_USED_IRQ 5
+#define ARM_EXTERNAL_IRQ 6
+#define ARM_EXTERNAL_FIQ 7
+
+void arm_irq_setup(void);
+void arm_irq_register(u32 irq_no, arm_irq_handler_t hndl);
+void arm_irq_enable(void);
+void arm_irq_disable(void);
+void arm_irq_wfi(void);
+
+#endif
diff --git a/tests/arm64/common/basic/arm_main.c b/tests/arm64/common/basic/arm_main.c
new file mode 100644
index 0000000..6e5725e
--- /dev/null
+++ b/tests/arm64/common/basic/arm_main.c
@@ -0,0 +1,675 @@
+/**
+ * Copyright (c) 2012 Jean-Christophe Dubois.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_main.c
+ * @author Jean-Christophe Dubois (
j...@tribudubois.net)
+ * @brief Basic firmware main file
+ */
+
+#include <arm_io.h>
+#include <arm_heap.h>
+#include <arm_mmu.h>
+#include <arm_irq.h>
+#include <arm_string.h>
+#include <arm_stdio.h>
+#include <arm_board.h>
+#include <dhry.h>
+#include <libfdt/libfdt.h>
+#include <libfdt/fdt_support.h>
+
+static unsigned long memory_size = 0x0;
+
+unsigned long arm_linux_memory_size(void)
+{
+ return memory_size;
+}
+
+/* Works in supervisor mode */
+void arm_init(void)
+{
+ arm_heap_init();
+
+ arm_irq_disable();
+
+ arm_irq_setup();
+
+ arm_stdio_init();
+
+ arm_board_timer_init(10000);
+
+ memory_size = arm_board_ram_size();
+
+ arm_board_timer_enable();
+
+ arm_irq_enable();
+}
+
+void arm_cmd_help(int argc, char **argv)
+{
+ arm_puts("help - List commands and their usage\n");
+ arm_puts("\n");
+ arm_puts("hi - Say hi to ARM test code\n");
+ arm_puts("\n");
+ arm_puts("hello - Say hello to ARM test code\n");
+ arm_puts("\n");
+ arm_puts("wfi_test - Run wait for irq instruction test for ARM test code\n");
+ arm_puts(" Usage: wfi_test [<msecs>]\n");
+ arm_puts(" <msecs> = delay in milliseconds to wait for\n");
+ arm_puts("\n");
+ arm_puts("mmu_setup - Setup MMU for ARM test code\n");
+ arm_puts("\n");
+ arm_puts("mmu_state - MMU is enabled/disabled for ARM test code\n");
+ arm_puts("\n");
+ arm_puts("mmu_test - Run MMU test suite for ARM test code\n");
+ arm_puts("\n");
+ arm_puts("mmu_cleanup - Cleanup MMU for ARM test code\n");
+ arm_puts("\n");
+ arm_puts("timer - Display timer information\n");
+ arm_puts("\n");
+ arm_puts("dhrystone - Dhrystone 2.1 benchmark\n");
+ arm_puts(" Usage: dhrystone [<iterations>]\n");
+ arm_puts("\n");
+ arm_puts("hexdump - Dump memory contents in hex format\n");
+ arm_puts(" Usage: hexdump <addr> <count>\n");
+ arm_puts(" <addr> = memory address in hex\n");
+ arm_puts(" <count> = byte count in hex\n");
+ arm_puts("\n");
+ arm_puts("copy - Copy to target memory from source memory\n");
+ arm_puts(" Usage: copy <dest> <src> <count>\n");
+ arm_puts(" <dest> = destination address in hex\n");
+ arm_puts(" <src> = source address in hex\n");
+ arm_puts(" <count> = byte count in hex\n");
+ arm_puts("\n");
+ arm_puts("start_linux - Start linux kernel\n");
+ arm_puts(" Usage: start_linux <kernel_addr> <initrd_addr> <initrd_size>\n");
+ arm_puts(" <kernel_addr> = kernel load address\n");
+ arm_puts(" <initrd_addr> = initrd load address\n");
+ arm_puts(" <initrd_size> = initrd size\n");
+ arm_puts("\n");
+ arm_puts("linux_cmdline - Show/Update linux command line\n");
+ arm_puts(" Usage: linux_cmdline <new_linux_cmdline> \n");
+ arm_puts(" <new_linux_cmdline> = linux command line\n");
+ arm_puts("\n");
+ arm_puts("linux_memory_size - Show/Update linux memory size\n");
+ arm_puts(" Usage: linux_memory_size <memory_size> \n");
+ arm_puts(" <memory_size> = memory size in hex\n");
+ arm_puts("\n");
+ arm_puts("autoexec - autoexec command list from flash\n");
+ arm_puts(" Usage: autoexec\n");
+ arm_puts("\n");
+ arm_puts("go - Jump to a given address\n");
+ arm_puts(" Usage: go <addr>\n");
+ arm_puts(" <addr> = jump address in hex\n");
+ arm_puts("\n");
+ arm_puts("reset - Reset the system\n");
+ arm_puts("\n");
+}
+
+void arm_cmd_hi(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("hi: no parameters required\n");
+ return;
+ }
+
+ arm_puts("hello\n");
+}
+
+void arm_cmd_hello(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("hello: no parameters required\n");
+ return;
+ }
+
+ arm_puts("hi\n");
+}
+
+void arm_cmd_wfi_test(int argc, char **argv)
+{
+ u64 tstamp;
+ char time[256];
+ int delay = 1000;
+
+ if (argc > 2) {
+ arm_puts ("wfi_test: could provide only <delay>\n");
+ return;
+ } else if (argc == 2) {
+ delay = arm_str2int(argv[1]);
+ }
+
+ arm_puts("Executing WFI instruction\n");
+ arm_board_timer_disable();
+ arm_board_timer_change_period(delay*1000);
+ arm_board_timer_enable();
+ tstamp = arm_board_timer_timestamp();
+ arm_irq_wfi();
+ tstamp = arm_board_timer_timestamp() - tstamp;
+ arm_board_timer_disable();
+ arm_board_timer_change_period(10000);
+ arm_board_timer_enable();
+ arm_puts("Resumed from WFI instruction\n");
+ arm_puts("Time spent in WFI: ");
+ arm_ulonglong2str(time, tstamp);
+ arm_puts(time);
+ arm_puts(" nsecs\n");
+}
+
+#if 0
+void arm_cmd_mmu_setup(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("mmu_setup: no parameters required\n");
+ return;
+ }
+
+ arm_mmu_setup();
+}
+#endif
+
+void arm_cmd_mmu_state(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("mmu_state: no parameters required\n");
+ return;
+ }
+
+ if (arm_mmu_is_enabled()) {
+ arm_puts("MMU Enabled\n");
+ } else {
+ arm_puts("MMU Disabled\n");
+ }
+}
+
+#if 0
+void arm_cmd_mmu_test(int argc, char **argv)
+{
+ char str[32];
+ u32 total = 0x0, pass = 0x0, fail = 0x0;
+
+ if (argc != 1) {
+ arm_puts ("mmu_test: no parameters required\n");
+ return;
+ }
+
+ arm_puts("MMU Section Test Suite ...\n");
+ total = 0x0;
+ pass = 0x0;
+ fail = 0x0;
+ arm_mmu_section_test(&total, &pass, &fail);
+ arm_puts(" Total: ");
+ arm_int2str(str, total);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" Pass : ");
+ arm_int2str(str, pass);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" Fail : ");
+ arm_int2str(str, fail);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts("MMU Page Test Suite ...\n");
+ total = 0x0;
+ pass = 0x0;
+ fail = 0x0;
+ arm_mmu_page_test(&total, &pass, &fail);
+ arm_puts(" Total: ");
+ arm_int2str(str, total);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" Pass : ");
+ arm_int2str(str, pass);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" Fail : ");
+ arm_int2str(str, fail);
+ arm_puts(str);
+ arm_puts("\n");
+}
+#endif
+
+void arm_cmd_mmu_cleanup(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("mmu_cleanup: no parameters required\n");
+ return;
+ }
+
+ arm_mmu_cleanup();
+}
+
+void arm_cmd_timer(int argc, char **argv)
+{
+ char str[32];
+ u64 irq_count, irq_delay, tstamp;
+
+ if (argc != 1) {
+ arm_puts ("timer: no parameters required\n");
+ return;
+ }
+
+ irq_count = arm_board_timer_irqcount();
+ irq_delay = arm_board_timer_irqdelay();
+ tstamp = arm_board_timer_timestamp();
+ arm_puts("Timer Information ...\n");
+ arm_puts(" IRQ Count: 0x");
+ arm_ulonglong2hexstr(str, irq_count);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" IRQ Delay: 0x");
+ arm_ulonglong2hexstr(str, irq_delay);
+ arm_puts(str);
+ arm_puts("\n");
+ arm_puts(" Time Stamp: 0x");
+ arm_ulonglong2hexstr(str, tstamp);
+ arm_puts(str);
+ arm_puts("\n");
+}
+
+void arm_cmd_dhrystone(int argc, char **argv)
+{
+ char str[32];
+ int iters = 1000000;
+ if (argc > 2) {
+ arm_puts ("dhrystone: could provide only <iter_number>\n");
+ return;
+ } else if (argc == 2) {
+ iters = arm_str2int(argv[1]);
+ } else {
+ arm_puts ("dhrystone: number of iterations not provided\n");
+ arm_puts ("dhrystone: using default ");
+ arm_int2str (str, iters);
+ arm_puts (str);
+ arm_puts (" iterations\n");
+ }
+ arm_board_timer_disable();
+ dhry_main(iters);
+ arm_board_timer_enable();
+}
+
+void arm_cmd_hexdump(int argc, char **argv)
+{
+ char str[32];
+ u32 *addr;
+ u32 i, count, len;
+ if (argc != 3) {
+ arm_puts ("hexdump: must provide <addr> and <count>\n");
+ return;
+ }
+ addr = (u32 *)arm_hexstr2ulonglong(argv[1]);
+ count = arm_hexstr2uint(argv[2]);
+ for (i = 0; i < (count / 4); i++) {
+ if (i % 4 == 0) {
+ arm_ulonglong2hexstr(str, (u64)&addr[i]);
+ len = arm_strlen(str);
+ while (len < 8) {
+ arm_puts("0");
+ len++;
+ }
+ arm_puts(str);
+ arm_puts(": ");
+ }
+ arm_uint2hexstr(str, addr[i]);
+ len = arm_strlen(str);
+ while (len < 8) {
+ arm_puts("0");
+ len++;
+ }
+ arm_puts(str);
+ if (i % 4 == 3) {
+ arm_puts("\n");
+ } else {
+ arm_puts(" ");
+ }
+ }
+ arm_puts("\n");
+}
+
+void arm_cmd_copy(int argc, char **argv)
+{
+ u64 tstamp;
+ char time[256];
+ u64 *dest, *src;
+ u32 i, count;
+ if (argc != 4) {
+ arm_puts ("copy: must provide <dest>, <src>, and <count>\n");
+ return;
+ }
+ dest = (u64 *)arm_hexstr2ulonglong(argv[1]);
+ src = (u64 *)arm_hexstr2ulonglong(argv[2]);
+ count = arm_hexstr2uint(argv[3]);
+ arm_board_timer_disable();
+ tstamp = arm_board_timer_timestamp();
+ for (i = 0; i < (count/sizeof(*dest)); i++) {
+ dest[i] = src[i];
+ }
+ tstamp = arm_board_timer_timestamp() - tstamp;
+ arm_board_timer_enable();
+ arm_ulonglong2str(time, tstamp);
+ arm_puts("copy took ");
+ arm_puts(time);
+ arm_puts(" ns for ");
+ arm_puts(argv[3]);
+ arm_puts(" bytes\n");
+}
+
+#define CONFIG_RAM_SIZE (arm_linux_memory_size() >> 20)
+#define CONFIG_NR_CPUS 2
+char linux_cmdline[1024];
+
+typedef void (* linux_entry_t) (u64 fdt_addr);
+extern void *__jump_addr;
+
+void dump_fdt(void *);
+
+void arm_cmd_start_linux(int argc, char **argv)
+{
+ u64 kernel_addr, fdt_addr;
+ u64 initrd_addr, initrd_size;
+ u64 release_addr;
+ int err;
+ char cfg_str[10];
+ u64 meminfo[2];
+
+ if (argc != 5) {
+ arm_puts ("start_linux: must provide <kernel_addr>, <initrd_addr>, <initrd_size> and <fdt_addr>\n");
+ return;
+ }
+
+ /* Parse the arguments from command line */
+ kernel_addr = arm_hexstr2ulonglong(argv[1]);
+ initrd_addr = arm_hexstr2ulonglong(argv[2]);
+ initrd_size = arm_hexstr2ulonglong(argv[3]);
+ fdt_addr = arm_hexstr2ulonglong(argv[4]);
+
+ meminfo[0] = arm_board_ram_start();
+ meminfo[1] = arm_board_ram_size();
+ /* Fillup/fixup the fdt blob with following:
+ * - initrd start, end
+ * - kernel cmd line
+ * - number of cpus */
+ if ((err = fdt_fixup_memory_banks((void *)fdt_addr, (&meminfo[0]),
+ (&meminfo[1]), 1))) {
+ arm_printf("%s: fdt_fixup_memory_banks() failed: %s\n", __func__,
+ fdt_strerror(err));
+ return;
+ }
+ sprintf(cfg_str, " mem=%dM maxcpus=%d",
+ (int)(meminfo[1] >> 20), CONFIG_NR_CPUS);
+ arm_strcat(linux_cmdline, cfg_str);
+ if ((err = fdt_chosen((void *)fdt_addr, 1))) {
+ arm_printf("%s: fdt_chosen() failed: %s\n", __func__,
+ fdt_strerror(err));
+ return;
+ }
+ if ((err = fdt_initrd((void *)fdt_addr, initrd_addr,
+ initrd_addr + initrd_size, 1))) {
+ arm_printf("%s: fdt_initrd() failed: %s\n", __func__,
+ fdt_strerror(err));
+ return;
+ }
+ release_addr = cpu_to_be64(((u64)(__jump_addr)));
+ do_fixup_by_compat((void *)fdt_addr, "arm,armv8", "cpu-release-addr",
+ &release_addr, sizeof(release_addr), 1);
+
+ /* Disable interrupts and timer */
+ arm_board_timer_disable();
+ arm_irq_disable();
+ arm_mmu_cleanup();
+
+ /* Jump to Linux Kernel
+ * r0 -> dtb address
+ */
+ arm_puts("Jumping into linux ...\n");
+ ((linux_entry_t)kernel_addr)(fdt_addr);
+
+ /* We should never reach here */
+ while (1);
+
+ return;
+}
+
+void arm_cmd_linux_cmdline(int argc, char **argv)
+{
+ if (argc >= 2) {
+ int cnt = 1;
+ linux_cmdline[0] = 0;
+
+ while (cnt < argc) {
+ arm_strcat(linux_cmdline, argv[cnt]);
+ arm_strcat(linux_cmdline, " ");
+ cnt++;
+ }
+ }
+
+ arm_puts ("linux_cmdline = \"");
+ arm_puts(linux_cmdline);
+ arm_puts ("\"\n");
+
+ return;
+}
+
+void arm_cmd_linux_memory_size(int argc, char **argv)
+{
+ char str[32];
+
+ if (argc == 2) {
+ memory_size = (u32)arm_hexstr2uint(argv[1]);
+ }
+
+ arm_puts ("linux_memory_size = 0x");
+ arm_uint2hexstr(str, memory_size);
+ arm_puts(str);
+ arm_puts (" Bytes\n");
+
+ return;
+}
+
+void arm_exec(char *line);
+
+void arm_cmd_autoexec(int argc, char **argv)
+{
+ static int lock = 0;
+ int len;
+ /* commands to execute are stored in NOR flash */
+ char *ptr = (char *)(arm_board_flash_addr() + 0xFF000);
+ char buffer[4096];
+
+ if (argc != 1) {
+ arm_puts ("autoexec: no parameters required\n");
+ return;
+ }
+
+ /* autoexec is not recursive */
+ if (lock) {
+ arm_puts("ignoring autoexec calling autoexec\n");
+ return;
+ }
+
+ lock = 1;
+
+ if ((len = arm_strlen(ptr))) {
+ int pos = 0;
+
+ /* copy commands from NOR flash */
+ arm_strcpy(buffer, ptr);
+
+ /* now we process them */
+ while (pos < len) {
+ ptr = &buffer[pos];
+
+ /* We need to separate the commands */
+ while ((buffer[pos] != '\r') &&
+ (buffer[pos] != '\n') &&
+ (buffer[pos] != 0)) {
+ pos++;
+ }
+ buffer[pos] = '\0';
+ pos++;
+
+ /* print the command */
+ arm_puts("autoexec(");
+ arm_puts(ptr);
+ arm_puts(")\n");
+ /* execute it */
+ arm_exec(ptr);
+ }
+
+ }
+
+ lock = 0;
+
+ return;
+}
+
+void arm_cmd_go(int argc, char **argv)
+{
+ char str[32];
+ void (* jump)(void);
+
+ if (argc != 2) {
+ arm_puts ("go: must provide destination address\n");
+ return;
+ }
+
+ arm_board_timer_disable();
+
+ jump = (void (*)(void))arm_hexstr2ulonglong(argv[1]);
+ arm_ulonglong2hexstr(str, (u64)jump);
+ arm_puts("Jumping to location 0x");
+ arm_puts(str);
+ arm_puts(" ...\n");
+ jump ();
+
+ arm_board_timer_enable();
+}
+
+void arm_cmd_reset(int argc, char **argv)
+{
+ if (argc != 1) {
+ arm_puts ("reset: no parameters required\n");
+ return;
+ }
+
+ arm_puts("System reset ...\n\n");
+
+ arm_board_reset();
+
+ while (1);
+}
+
+#define ARM_MAX_ARG_SIZE 32
+
+void arm_exec(char *line)
+{
+ int argc = 0, pos = 0, cnt = 0;
+ char *argv[ARM_MAX_ARG_SIZE];
+
+ while (line[pos] && (argc < ARM_MAX_ARG_SIZE)) {
+ if ((line[pos] == '\r') ||
+ (line[pos] == '\n')) {
+ line[pos] = '\0';
+ break;
+ }
+ if (line[pos] == ' ') {
+ if (cnt > 0) {
+ line[pos] = '\0';
+ cnt = 0;
+ }
+ } else {
+ if (cnt == 0) {
+ argv[argc] = &line[pos];
+ argc++;
+ }
+ cnt++;
+ }
+ pos++;
+ }
+
+ if (argc) {
+ if (arm_strcmp(argv[0], "help") == 0) {
+ arm_cmd_help(argc, argv);
+ } else if (arm_strcmp(argv[0], "hi") == 0) {
+ arm_cmd_hi(argc, argv);
+ } else if (arm_strcmp(argv[0], "hello") == 0) {
+ arm_cmd_hello(argc, argv);
+ } else if (arm_strcmp(argv[0], "wfi_test") == 0) {
+ arm_cmd_wfi_test(argc, argv);
+#if 0
+ } else if (arm_strcmp(argv[0], "mmu_setup") == 0) {
+ arm_cmd_mmu_setup(argc, argv);
+#endif
+ } else if (arm_strcmp(argv[0], "mmu_state") == 0) {
+ arm_cmd_mmu_state(argc, argv);
+#if 0
+ } else if (arm_strcmp(argv[0], "mmu_test") == 0) {
+ arm_cmd_mmu_test(argc, argv);
+#endif
+ } else if (arm_strcmp(argv[0], "mmu_cleanup") == 0) {
+ arm_cmd_mmu_cleanup(argc, argv);
+ } else if (arm_strcmp(argv[0], "timer") == 0) {
+ arm_cmd_timer(argc, argv);
+ } else if (arm_strcmp(argv[0], "dhrystone") == 0) {
+ arm_cmd_dhrystone(argc, argv);
+ } else if (arm_strcmp(argv[0], "hexdump") == 0) {
+ arm_cmd_hexdump(argc, argv);
+ } else if (arm_strcmp(argv[0], "copy") == 0) {
+ arm_cmd_copy(argc, argv);
+ } else if (arm_strcmp(argv[0], "start_linux") == 0) {
+ arm_cmd_start_linux(argc, argv);
+ } else if (arm_strcmp(argv[0], "linux_cmdline") == 0) {
+ arm_cmd_linux_cmdline(argc, argv);
+ } else if (arm_strcmp(argv[0], "linux_memory_size") == 0) {
+ arm_cmd_linux_memory_size(argc, argv);
+ } else if (arm_strcmp(argv[0], "autoexec") == 0) {
+ arm_cmd_autoexec(argc, argv);
+ } else if (arm_strcmp(argv[0], "go") == 0) {
+ arm_cmd_go(argc, argv);
+ } else if (arm_strcmp(argv[0], "reset") == 0) {
+ arm_cmd_reset(argc, argv);
+ } else {
+ arm_puts("Unknown command\n");
+ }
+ }
+}
+
+#define ARM_MAX_CMD_STR_SIZE 256
+
+/* Works in user mode */
+void arm_main(void)
+{
+ char line[ARM_MAX_CMD_STR_SIZE];
+
+ /* Setup board specific linux default cmdline */
+ arm_board_linux_default_cmdline(linux_cmdline,
+ sizeof(linux_cmdline));
+
+ arm_puts(arm_board_name());
+ arm_puts(" Basic Firmware\n\n");
+
+ arm_board_init();
+
+ while(1) {
+ arm_puts("basic# ");
+
+ arm_gets(line, ARM_MAX_CMD_STR_SIZE, '\n');
+
+ arm_exec(line);
+ }
+}
diff --git a/tests/arm64/common/basic/arm_math.c b/tests/arm64/common/basic/arm_math.c
new file mode 100644
index 0000000..0fbbf87
--- /dev/null
+++ b/tests/arm64/common/basic/arm_math.c
@@ -0,0 +1,117 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_math.c
+ * @brief commonly required math operations
+ */
+
+#include <arm_math.h>
+
+static const unsigned char byte_reverse_table[] =
+{
+ 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+ 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+ 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+ 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+ 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+ 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+ 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+ 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+ 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+ 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
+};
+
+static inline u32 do_fls64(u64 value)
+{
+ u32 num_bits = 0;
+ if (value & 0xFFFF000000000000ULL) {
+ num_bits += 16;
+ value = value >> 16;
+ }
+ if (value & 0x0000FFFF00000000ULL) {
+ num_bits += 16;
+ value = value >> 16;
+ }
+ if (value & 0x00000000FFFF0000ULL) {
+ num_bits += 16;
+ value = value >> 16;
+ }
+ if (value & 0x000000000000FF00ULL) {
+ num_bits += 8;
+ value = value >> 8;
+ }
+ if (value & 0x00000000000000F0ULL) {
+ num_bits += 4;
+ value = value >> 4;
+ }
+ if (value & 0x000000000000000CULL) {
+ num_bits += 2;
+ value = value >> 2;
+ }
+ if (value & 0x0000000000000003ULL) {
+ num_bits += 2;
+ value = value >> 2;
+ }
+ return num_bits;
+}
+
+u64 do_udiv64(u64 dividend, u64 divisor, u64 * remainder)
+{
+ *remainder = (dividend % divisor);
+ return (dividend / divisor);
+}
+
+static inline u32 do_fls32(u32 value)
+{
+ u32 num_bits = 0;
+ if (value & 0xFFFF0000) {
+ num_bits += 16;
+ value = value >> 16;
+ }
+ if (value & 0x0000FF00) {
+ num_bits += 8;
+ value = value >> 8;
+ }
+ if (value & 0x000000F0) {
+ num_bits += 4;
+ value = value >> 4;
+ }
+ if (value & 0x0000000C) {
+ num_bits += 2;
+ value = value >> 2;
+ }
+ if (value & 0x00000003) {
+ num_bits += 2;
+ value = value >> 2;
+ }
+ return num_bits;
+}
+
+u32 do_udiv32(u32 dividend, u32 divisor, u32 * remainder)
+{
+ *remainder = (dividend % divisor);
+ return (dividend / divisor);
+}
+
diff --git a/tests/arm64/common/basic/arm_math.h b/tests/arm64/common/basic/arm_math.h
new file mode 100644
index 0000000..f0e1304
--- /dev/null
+++ b/tests/arm64/common/basic/arm_math.h
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_math.h
+ * @brief commonly required math operations
+ */
+
+#ifndef __ARM_MATH_H_
+#define __ARM_MATH_H_
+
+#include <arm_types.h>
+
+#define do_abs(x) ((x) < 0 ? -(x) : (x))
+
+static inline u64 arm_udiv64(u64 value, u64 divisor)
+{
+ return (value / divisor);
+}
+
+static inline u64 arm_umod64(u64 value, u64 divisor)
+{
+ return (value % divisor);
+}
+
+static inline u32 arm_udiv32(u32 value, u32 divisor)
+{
+ return (value / divisor);
+}
+
+static inline u32 arm_umod32(u32 value, u32 divisor)
+{
+ return (value % divisor);
+}
+
+static inline s32 arm_sdiv32(s32 value, s32 divisor)
+{
+ if ((value * divisor) < 0) {
+ return -(do_abs(value) / do_abs(divisor));
+ } else { /* positive value */
+ return (do_abs(value) / do_abs(divisor));
+ }
+}
+
+#endif /* __ARM_MATH_H_ */
diff --git a/tests/arm64/common/basic/arm_mmu.c b/tests/arm64/common/basic/arm_mmu.c
new file mode 100644
index 0000000..78cde71
--- /dev/null
+++ b/tests/arm64/common/basic/arm_mmu.c
@@ -0,0 +1,235 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_mmu_v7.c
+ * @brief source file for MMU functions
+ */
+
+#include <arm_board.h>
+#include <arm_inline_asm.h>
+#include <arm_defines.h>
+#include <arm_mmu.h>
+#include <arm_stdio.h>
+
+#if 0
+u32 __attribute__((aligned(TTBL_L1TBL_SIZE))) l1[TTBL_L1TBL_SIZE / 4];
+u32 __attribute__((aligned(TTBL_L2TBL_SIZE))) l2[TTBL_L2TBL_SIZE / 4];
+u32 l2_mapva;
+#endif
+
+u32 test_area_pa;
+u32 test_area_size;
+
+extern void _switch_to_user_mode (u32, u32);
+
+#define ARM_MMU_TEST_SWITCH_TO_USER() _switch_to_user_mode(0x0, 0x0)
+#define ARM_MMU_TEST_SWITCH_TO_SUPER() asm volatile("svc 0x1":::"memory", "cc")
+
+u64 test_data_abort_fsc;
+u64 test_data_abort_far;
+u64 test_data_abort_wnr;
+u64 test_data_abort_dom;
+u32 test_data_abort_result;
+
+void arm_sync_abort(struct pt_regs *regs)
+{
+ u64 esr, far, ec, iss, wnr;
+ u64 fsc;
+
+ esr = mrs(esr_el1);
+ far = mrs(far_el1);
+
+ ec = (esr & ESR_EC_MASK) >> ESR_EC_SHIFT;
+ iss = (esr & ESR_ISS_MASK) >> ESR_ISS_SHIFT;
+
+ switch (ec) {
+ case EC_TRAP_SVC_A64:
+ if((iss & 0xffff) == 1) {
+ /* Request to switch to supervisor mode */
+ regs->pstate &= ~PSR_MODE_MASK;
+ regs->pstate |= PSR_MODE_EL1t;
+ regs->pc += 4;
+ return;
+ }
+ break;
+ case EC_TRAP_LWREL_DATA_ABORT:
+ fsc = (iss & ISS_ABORT_FSC_MASK) >> ISS_ABORT_FSC_SHIFT;
+ wnr = (iss & ISS_ABORT_WNR_MASK) >> ISS_ABORT_WNR_SHIFT;
+ if ((fsc == test_data_abort_fsc) &&
+ (far == test_data_abort_far) &&
+ (wnr == test_data_abort_wnr)) {
+ test_data_abort_result = 1;
+ regs->pc += 4;
+ return;
+ }
+ break;
+ }
+ arm_printf("Bad synchronous exception @ PC: 0x%X\n", regs->pc);
+ arm_printf("ESR: 0x%08X (EC:0x%X, ISS:0x%X)\n", esr, ec, iss);
+ arm_printf("LR: 0x%X, FAR: 0x%X, PSTATE: 0x%X\n", regs->lr, far, regs->pstate);
+ arm_printf(" General Purpose Registers");
+ {
+ int ite;
+ for (ite = 0; ite < 30; ite++) {
+ if (ite % 2 == 0)
+ arm_printf("\n");
+ arm_printf(" X%02d=0x%016x ", ite, regs->gpr[ite]);
+ }
+ }
+ arm_printf("\n");
+ while(1);
+}
+
+bool arm_mmu_is_enabled(void)
+{
+ u32 sctlr = mrs(sctlr_el1);
+
+ if (sctlr & SCTLR_M_MASK) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+extern u8 _code_start;
+extern u8 _code_end;
+
+void arm_mmu_setup(void)
+{
+ u64 *l1;
+ u64 val, sec_tmpl = 0x0;
+ u32 sctlr = mrs(sctlr_el1);
+
+ /* If MMU already enabled then return */
+ if (sctlr & SCTLR_M_MASK) {
+ return;
+ }
+
+ /* We place the L1 page table at a page-aligned address after _code_end */
+ l1 = (u64 *)(((u64)&_code_end + TTBL_TABLE_SIZE) & ~(TTBL_TABLE_SIZE - 1));
+
+ /* Reset memory for L1 */
+ for (val = 0; val < (TTBL_TABLE_ENTCNT); val++) {
+ l1[val] = 0x0;
+ }
+
+ /* SuperSection entry template for code */
+ sec_tmpl = (TTBL_STAGE1_LOWER_AF_MASK | TTBL_VALID_MASK);
+ sec_tmpl |= (TTBL_AP_SRW_U << TTBL_STAGE1_LOWER_AP_SHIFT);
+ sec_tmpl |= (1 << 11);
+
+ /* Create 1GB super-section entry for Device Region from 0x00_0000_0000 */
+ val = ((AINDEX_SO << TTBL_STAGE1_LOWER_AINDEX_SHIFT) & TTBL_STAGE1_LOWER_AINDEX_MASK);
+ val |= (0x0 << TTBL_STAGE1_LOWER_SH_SHIFT) | 0x00000000; /* Non-shareable */
+ l1[0x00000000/(1 << 30)] = (sec_tmpl | val);
+
+ /* Create 1GB super-section entry for RAM from 0x00_8000_0000 */
+ val = ((AINDEX_NORMAL_WB << TTBL_STAGE1_LOWER_AINDEX_SHIFT) & TTBL_STAGE1_LOWER_AINDEX_MASK);
+ val |= (0x3 << TTBL_STAGE1_LOWER_SH_SHIFT) | 0x80000000; /* Inner-shareable */
+ l1[0x80000000/(1 << 30)] = (sec_tmpl | val);
+
+ /* Setup Translation Control Register */
+ val = 0;
+ /* Upto 39bits of VA will allow us to continue with 3 levels of stage-1 page-tables
+ * so we program TCR_EL1[T0SZ] = 0x19 */
+ val &= (~TCR_T0SZ_MASK);
+ val |= (0x19 << TCR_T0SZ_SHIFT);
+ val &= (~TCR_PS_MASK);
+ val |= (0x2 << TCR_PS_SHIFT); /* PASize: 0x2 => PA[39:0] */
+ val &= (~TCR_SH0_MASK);
+ val |= (0x3 << TCR_SH0_SHIFT); /* Shareability: 0x3 - inner-shareable */
+ val &= (~TCR_ORGN0_MASK);
+ val |= (0x1 << TCR_ORGN0_SHIFT); /* Cacheability: 0x1 - write-back */
+ val &= (~TCR_IRGN0_MASK);
+ val |= (0x1 << TCR_IRGN0_SHIFT); /* Cacheability: 0x1 - write-back */
+ msr(tcr_el1, val);
+
+ /* Initialize MAIR */
+ msr(mair_el1, MAIR_INITVAL);
+
+ /* Write TTBR0 */
+ msr(ttbr0_el1, (u64)l1);
+
+ /* Enable MMU */
+ sctlr |= SCTLR_I_MASK | SCTLR_C_MASK | SCTLR_M_MASK | SCTLR_AFE_MASK;
+ msr(sctlr_el1, sctlr);
+
+ asm("dsb sy\n\tisb\n\t":::"memory", "cc");
+
+ return;
+}
+
+void data_cache_flush_all(void)
+{
+ register u32 val, set, way, line, i, j;
+ register int slog, wlog, llog, loc;
+ int clevel = 0, clidr;
+
+ dsb();
+ isb();
+ clidr = mrs(CLIDR_EL1);
+ loc = ((clidr >> 24) & 0x7);
+
+ while(clevel < loc) {
+ /* Select the cache-level in CCSELR_EL1 */
+ val = (clevel << 1);
+ msr(CSSELR_EL1, val);
+ isb();
+ /* Read the Cache Sized ID Register */
+ val = mrs(CCSIDR_EL1);
+ set = ((val & 0x0FFFE000) >> 13) + 1;
+ way = ((val & 0x00001FF8) >> 3) + 1;
+ line = (1 << (((val & 0x7) >> 0) + 2)) * sizeof(unsigned int);
+
+#define log2n(n, val) { asm("clz %0, %1":"=r"(val):"r"(n)); val = (63 - val); }
+
+ log2n(set, slog);
+ log2n(way, wlog);
+ log2n(line, llog);
+
+ for (i=0; i<set; i++) {
+ for (j=0; j<way; j++) {
+ val = (j << (32-wlog)) | (i << llog) | (clevel << 1);
+ asm volatile("dc cisw, %0"::"r"(val):"memory","cc");
+ }
+ }
+
+ dsb();
+ isb();
+ clevel++;
+ }
+}
+
+void arm_mmu_cleanup(void)
+{
+ u32 sctlr = mrs(sctlr_el1);
+
+ /* If MMU already disabled then return */
+ if (!(sctlr & SCTLR_M_MASK)) {
+ return;
+ }
+
+ data_cache_flush_all();
+ /* Disable MMU */
+ sctlr &= ~SCTLR_M_MASK;
+ msr_sync(sctlr_el1, sctlr);
+
+ return;
+}
+
diff --git a/tests/arm64/common/basic/arm_mmu.h b/tests/arm64/common/basic/arm_mmu.h
new file mode 100644
index 0000000..9fbea7d
--- /dev/null
+++ b/tests/arm64/common/basic/arm_mmu.h
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_mmu.h
+ * @brief Header file for MMU functions
+ */
+
+#ifndef __ARM_MMU_H_
+#define __ARM_MMU_H_
+
+#include <arm_types.h>
+
+void arm_sync_abort(struct pt_regs *regs);
+void arm_mmu_section_test(u32 * total, u32 * pass, u32 * fail);
+void arm_mmu_page_test(u32 * total, u32 * pass, u32 * fail);
+bool arm_mmu_is_enabled(void);
+void arm_mmu_setup(void);
+void arm_mmu_cleanup(void);
+
+#endif /* __ARM_MMU_H_ */
diff --git a/tests/arm64/common/basic/arm_stdio.c b/tests/arm64/common/basic/arm_stdio.c
new file mode 100644
index 0000000..a65d2b0
--- /dev/null
+++ b/tests/arm64/common/basic/arm_stdio.c
@@ -0,0 +1,360 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_stdio.c
+ * @brief source file for common input/output functions
+ */
+
+#include <arm_board.h>
+#include <arm_stdio.h>
+
+void arm_stdio_init(void)
+{
+ int rc;
+
+ rc = arm_board_serial_init();
+ if (rc) {
+ while (1);
+ }
+}
+
+void arm_puts(const char * str)
+{
+ while (*str) {
+ arm_board_serial_putc(*str);
+ str++;
+ }
+}
+
+void arm_gets(char *s, int maxwidth, char endchar)
+{
+ char *retval;
+ char ch;
+ retval = s;
+ ch = arm_board_serial_getc();
+ while (ch != endchar && maxwidth > 0) {
+ *retval = ch;
+ retval++;
+ maxwidth--;
+ if (maxwidth == 0)
+ break;
+ ch = arm_board_serial_getc();
+ }
+ *retval = '\0';
+ return;
+}
+
+#define PAD_RIGHT 1
+#define PAD_ZERO 2
+#define PAD_ALTERNATE 4
+#define PRINT_BUF_LEN 64
+
+#define va_start(v,l) __builtin_va_start((v),l)
+#define va_end __builtin_va_end
+#define va_arg __builtin_va_arg
+typedef __builtin_va_list va_list;
+
+static void printc(char **out, u32 *out_len, char ch)
+{
+ if (out) {
+ if (*out) {
+ if (out_len && (0 < *out_len)) {
+ **out = ch;
+ ++(*out);
+ (*out_len)--;
+ } else {
+ **out = ch;
+ ++(*out);
+ }
+ }
+ } else {
+ arm_board_serial_putc(ch);
+ }
+}
+
+static int prints(char **out, u32 *out_len, const char *string, int width, int flags)
+{
+ int pc = 0;
+ char padchar = ' ';
+
+ if (width > 0) {
+ int len = 0;
+ const char *ptr;
+ for (ptr = string; *ptr; ++ptr)
+ ++len;
+ if (len >= width)
+ width = 0;
+ else
+ width -= len;
+ if (flags & PAD_ZERO)
+ padchar = '0';
+ }
+ if (!(flags & PAD_RIGHT)) {
+ for (; width > 0; --width) {
+ printc(out, out_len, padchar);
+ ++pc;
+ }
+ }
+ for (; *string; ++string) {
+ printc(out, out_len, *string);
+ ++pc;
+ }
+ for (; width > 0; --width) {
+ printc(out, out_len, padchar);
+ ++pc;
+ }
+
+ return pc;
+}
+
+static int printi(char **out, u32 *out_len, long long i, int b, int sg,
+ int width, int flags, int letbase)
+{
+ char print_buf[PRINT_BUF_LEN];
+ char *s;
+ int t, neg = 0, pc = 0;
+ unsigned long long u = i;
+
+ if (sg && b == 10 && i < 0) {
+ neg = 1;
+ u = -i;
+ }
+
+ s = print_buf + PRINT_BUF_LEN - 1;
+ *s = '\0';
+
+ if (!u) {
+ *--s = '0';
+ } else {
+ while (u) {
+ t = (u % b);
+ if (t >= 10)
+ t += letbase - '0' - 10;
+ *--s = t + '0';
+ u = (u / b);
+ }
+ }
+
+ if (flags & PAD_ALTERNATE) {
+ if ((b == 16) && (letbase == 'A')) {
+ *--s = 'X';
+ } else if ((b == 16) && (letbase == 'a')) {
+ *--s = 'x';
+ }
+ *--s = '0';
+ }
+
+ if (neg) {
+ if (width && (flags & PAD_ZERO)) {
+ printc(out, out_len, '-');
+ ++pc;
+ --width;
+ } else {
+ *--s = '-';
+ }
+ }
+
+ return pc + prints(out, out_len, s, width, flags);
+}
+
+static int print(char **out, u32 *out_len, const char *format, va_list args)
+{
+ int width, flags, acnt = 0;
+ int pc = 0;
+ char scr[2];
+ unsigned long long tmp;
+
+ for (; *format != 0; ++format) {
+ if (*format == '%') {
+ ++format;
+ width = flags = 0;
+ if (*format == '\0')
+ break;
+ if (*format == '%')
+ goto out;
+ /* Get flags */
+ if (*format == '-') {
+ ++format;
+ flags = PAD_RIGHT;
+ }
+ if (*format == '#') {
+ ++format;
+ flags |= PAD_ALTERNATE;
+ }
+ while (*format == '0') {
+ ++format;
+ flags |= PAD_ZERO;
+ }
+ /* Get width */
+ for (; *format >= '0' && *format <= '9'; ++format) {
+ width *= 10;
+ width += *format - '0';
+ }
+ if (*format == 's') {
+ char *s = va_arg(args, char *);
+ acnt += sizeof(char *);
+ pc += prints(out, out_len,
+ s ? s : "(null)", width, flags);
+ continue;
+ }
+ if (*format == 'd') {
+ pc += printi(out, out_len,
+ va_arg(args, int),
+ 10, 1, width, flags, '0');
+ acnt += sizeof(int);
+ continue;
+ }
+ if (*format == 'x') {
+ pc += printi(out, out_len,
+ va_arg(args, unsigned int),
+ 16, 0, width, flags, 'a');
+ acnt += sizeof(unsigned int);
+ continue;
+ }
+ if (*format == 'X') {
+ pc += printi(out, out_len,
+ va_arg(args, unsigned int),
+ 16, 0, width, flags, 'A');
+ acnt += sizeof(unsigned int);
+ continue;
+ }
+ if (*format == 'u') {
+ pc += printi(out, out_len,
+ va_arg(args, unsigned int),
+ 10, 0, width, flags, 'a');
+ acnt += sizeof(unsigned int);
+ continue;
+ }
+ if (*format == 'p') {
+ pc += printi(out, out_len,
+ va_arg(args, unsigned long),
+ 16, 0, width, flags, 'a');
+ acnt += sizeof(unsigned long);
+ continue;
+ }
+ if (*format == 'P') {
+ pc += printi(out, out_len,
+ va_arg(args, unsigned long),
+ 16, 0, width, flags, 'A');
+ acnt += sizeof(unsigned long);
+ continue;
+ }
+ if (*format == 'l' && *(format + 1) == 'l') {
+ while (acnt & (sizeof(unsigned long long)-1)) {
+ va_arg(args, int);
+ acnt += sizeof(int);
+ }
+ if (sizeof(unsigned long long) ==
+ sizeof(unsigned long)) {
+ tmp = va_arg(args, unsigned long long);
+ acnt += sizeof(unsigned long long);
+ } else {
+ ((unsigned long *)&tmp)[0] =
+ va_arg(args, unsigned long);
+ ((unsigned long *)&tmp)[1] =
+ va_arg(args, unsigned long);
+ acnt += 2*sizeof(unsigned long);
+ }
+ if (*(format + 2) == 'u') {
+ format += 2;
+ pc += printi(out, out_len, tmp,
+ 10, 0, width, flags, 'a');
+ } else if (*(format + 2) == 'x') {
+ format += 2;
+ pc += printi(out, out_len, tmp,
+ 16, 0, width, flags, 'a');
+ } else if (*(format + 2) == 'X') {
+ format += 2;
+ pc += printi(out, out_len, tmp,
+ 16, 0, width, flags, 'A');
+ } else {
+ format += 1;
+ pc += printi(out, out_len, tmp,
+ 10, 1, width, flags, '0');
+ }
+ continue;
+ } else if (*format == 'l') {
+ if (*(format + 1) == 'x') {
+ format += 1;
+ pc += printi(out, out_len,
+ va_arg(args, unsigned long),
+ 16, 0, width, flags, 'a');
+ acnt += sizeof(unsigned long);
+ } else if (*(format + 1) == 'X') {
+ format += 1;
+ pc += printi(out, out_len,
+ va_arg(args, unsigned long),
+ 16, 0, width, flags, 'A');
+ acnt += sizeof(unsigned long);
+ } else {
+ pc += printi(out, out_len,
+ va_arg(args, long),
+ 10, 1, width, flags, '0');
+ acnt += sizeof(long);
+ }
+ }
+ if (*format == 'c') {
+ /* char are converted to int then pushed on the stack */
+ scr[0] = va_arg(args, int);
+ scr[1] = '\0';
+ pc += prints(out, out_len, scr, width, flags);
+ acnt += sizeof(int);
+ continue;
+ }
+ } else {
+out:
+ printc(out, out_len, *format);
+ ++pc;
+ }
+ }
+ if (out)
+ **out = '\0';
+ return pc;
+}
+
+int arm_sprintf(char *out, const char *format, ...)
+{
+ va_list args;
+ int retval;
+ va_start(args, format);
+ retval = print(&out, NULL, format, args);
+ va_end(args);
+ return retval;
+}
+
+int arm_snprintf(char *out, u32 out_sz, const char *format, ...)
+{
+ va_list args;
+ int retval;
+ va_start(args, format);
+ retval = print(&out, &out_sz, format, args);
+ va_end(args);
+ return retval;
+}
+
+int arm_printf(const char *format, ...)
+{
+ va_list args;
+ int retval;
+ va_start(args, format);
+ retval = print(NULL, NULL, format, args);
+ va_end(args);
+ return retval;
+}
+
diff --git a/tests/arm64/common/basic/arm_stdio.h b/tests/arm64/common/basic/arm_stdio.h
new file mode 100644
index 0000000..2e29165
--- /dev/null
+++ b/tests/arm64/common/basic/arm_stdio.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_stdio.h
+ * @brief Header file for common input/output functions
+ */
+
+#ifndef __ARM_STDIO_H_
+#define __ARM_STDIO_H_
+
+#include <arm_types.h>
+
+void arm_putc(char ch);
+char arm_getc(void);
+void arm_stdio_init(void);
+void arm_puts(const char * str);
+void arm_gets(char *s, int maxwidth, char endchar);
+int arm_sprintf(char *out, const char *format, ...);
+int arm_snprintf(char *out, u32 out_sz, const char *format, ...);
+int arm_printf(const char *format, ...);
+
+#endif /* __ARM_STDIO_H_ */
diff --git a/tests/arm64/common/basic/arm_string.c b/tests/arm64/common/basic/arm_string.c
new file mode 100644
index 0000000..dc8beca
--- /dev/null
+++ b/tests/arm64/common/basic/arm_string.c
@@ -0,0 +1,357 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_string.c
+ * @brief source file for common string functions
+ */
+
+#include <arm_string.h>
+#include <arm_math.h>
+
+void *arm_memcpy(void *dest, const void *src, unsigned int count)
+{
+ u8 *dst8 = (u8 *) dest;
+ u8 *src8 = (u8 *) src;
+
+ if (count & 1) {
+ dst8[0] = src8[0];
+ dst8 += 1;
+ src8 += 1;
+ }
+
+ count /= 2;
+ while (count--) {
+ dst8[0] = src8[0];
+ dst8[1] = src8[1];
+
+ dst8 += 2;
+ src8 += 2;
+ }
+
+ return dest;
+}
+
+void *arm_memmove(void *dest, const void *src, unsigned int count)
+{
+ u8 *dst8 = (u8 *) dest;
+ const u8 *src8 = (u8 *) src;
+
+ if(dest == src)
+ return dest;
+
+ if (src8 > dst8) {
+ if (count & 1) {
+ dst8[0] = src8[0];
+ dst8 += 1;
+ src8 += 1;
+ }
+
+ count /= 2;
+ while (count--) {
+ dst8[0] = src8[0];
+ dst8[1] = src8[1];
+
+ dst8 += 2;
+ src8 += 2;
+ }
+ } else {
+ dst8 += count;
+ src8 += count;
+
+ if (count & 1) {
+ dst8 -= 1;
+ src8 -= 1;
+ dst8[0] = src8[0];
+ }
+
+ count /= 2;
+ while (count--) {
+ dst8 -= 2;
+ src8 -= 2;
+
+ dst8[0] = src8[0];
+ dst8[1] = src8[1];
+ }
+ }
+
+ return dest;
+}
+
+void *arm_memset(void *dest, int c, unsigned int count)
+{
+ u8 *dst8 = (u8 *) dest;
+ u8 ch = (u8) c;
+
+ if (count & 1) {
+ dst8[0] = ch;
+ dst8 += 1;
+ }
+
+ count /= 2;
+ while (count--) {
+ dst8[0] = ch;
+ dst8[1] = ch;
+ dst8 += 2;
+ }
+
+ return dest;
+}
+
+int arm_memcmp(const void *s1, const void *s2, unsigned int count)
+{
+ u8 *p1 = (u8 *) s1;
+ u8 *p2 = (u8 *) s2;
+ if (count != 0) {
+ do {
+ if (*p1++ != *p2++)
+ return (*--p1 - *--p2);
+ } while (--count != 0);
+ }
+ return (0);
+}
+
+char *arm_memchr(const char *p, int ch, int count)
+{
+ int i;
+ for(i=0; i<count; i++) {
+ if ((*p)==ch) {
+ return((char *)p);
+ }
+ p++;
+ }
+ return((char *)NULL);
+}
+
+char *arm_strchr(const char *p, int ch)
+{
+ do {
+ if ((*p)==ch) {
+ return((char *)p);
+ }
+ } while((*p++)!='\0');
+ return((char *)NULL);
+}
+
+unsigned int arm_strlen(const char *s)
+{
+ unsigned int ret = 0;
+ while (s[ret]) {
+ ret++;
+ }
+ return ret;
+}
+
+char *arm_strcpy(char *dest, const char *src)
+{
+ u32 i;
+ for (i = 0; src[i] != '\0'; ++i)
+ dest[i] = src[i];
+ dest[i] = '\0';
+ return dest;
+}
+
+char *arm_strcat(char *dest, const char *src)
+{
+ arm_strcpy(&dest[arm_strlen(dest)], src);
+
+ return dest;
+}
+
+int arm_strcmp(const char *a, const char *b)
+{
+ while (*a == *b) {
+ if (*a == '\0' || *b == '\0') {
+ return (unsigned char)*a - (unsigned char)*b;
+ }
+ ++a;
+ ++b;
+ }
+ return (unsigned char)*a - (unsigned char)*b;
+}
+
+int arm_str2int(char *src)
+{
+ int val = 0, pos = 0, minus = 0;
+
+ if (src[pos] == '-') {
+ minus = 1;
+ pos++;
+ }
+
+ while (src[pos]) {
+ val = 10 * val + (src[pos] - '0');
+ pos++;
+ }
+
+ return (minus) ? -val : val;
+}
+
+void arm_int2str(char *dst, int src)
+{
+ int val, count = 0, pos = 0;
+ static const char intchars[] = "0123456789";
+
+ val = src;
+ while (val) {
+ count++;
+ val = val / 10;
+ }
+ if (src < 0) {
+ count++;
+ }
+
+ val = (src < 0) ? -src : src;
+ while (val) {
+ dst[count - pos - 1] = intchars[val % 10];
+ val = val / 10;
+ pos++;
+ }
+ if (src < 0) {
+ dst[0] = '-';
+ }
+
+ if (count == 0) {
+ dst[count] = '0';
+ count++;
+ }
+
+ dst[count] = '\0';
+}
+
+void arm_ulonglong2str(char *dst, unsigned long long src)
+{
+ unsigned long long val;
+ int count = 0, pos = 0;
+ static const char intchars[] = "0123456789";
+
+ val = src;
+ while (val) {
+ count++;
+ val = val / 10;
+ }
+ if (src < 0) {
+ count++;
+ }
+
+ val = (src < 0) ? -src : src;
+ while (val) {
+ dst[count - pos - 1] = intchars[val % 10];
+ val = val / 10;
+ pos++;
+ }
+ if (src < 0) {
+ dst[0] = '-';
+ }
+
+ if (count == 0) {
+ dst[count] = '0';
+ count++;
+ }
+
+ dst[count] = '\0';
+}
+
+unsigned int arm_hexstr2uint(char * src)
+{
+ unsigned int val = 0x0;
+ int pos = 0;
+
+ if ((src[0] == '0') && (src[1] == 'x')) {
+ pos = 2;
+ }
+
+ while (src[pos]) {
+ if (('0' <= src[pos]) && (src[pos] <= '9')) {
+ val = val * 16 + (src[pos] - '0');
+ } else if (('A' <= src[pos]) && (src[pos] <= 'F')) {
+ val = val * 16 + (src[pos] - 'A' + 10);
+ } else if (('a' <= src[pos]) && (src[pos] <= 'f')) {
+ val = val * 16 + (src[pos] - 'a' + 10);
+ }
+ pos++;
+ }
+
+ return val;
+}
+
+unsigned long long arm_hexstr2ulonglong(char * src)
+{
+ unsigned long long val = 0x0;
+ int pos = 0;
+
+ if ((src[0] == '0') && (src[1] == 'x')) {
+ pos = 2;
+ }
+
+ while (src[pos]) {
+ if (('0' <= src[pos]) && (src[pos] <= '9')) {
+ val = val * 16 + (src[pos] - '0');
+ } else if (('A' <= src[pos]) && (src[pos] <= 'F')) {
+ val = val * 16 + (src[pos] - 'A' + 10);
+ } else if (('a' <= src[pos]) && (src[pos] <= 'f')) {
+ val = val * 16 + (src[pos] - 'a' + 10);
+ }
+ pos++;
+ }
+
+ return val;
+}
+
+void arm_uint2hexstr(char *dst, unsigned int src)
+{
+ int ite, pos = 0;
+ static const char hexchars[] = "0123456789ABCDEF";
+
+ for (ite = 0; ite < 8; ite++) {
+ if ((pos == 0) && !((src >> (4 * (8 - ite - 1))) & 0xF)) {
+ continue;
+ }
+ dst[pos] = hexchars[(src >> (4 * (8 - ite - 1))) & 0xF];
+ pos++;
+ }
+
+ if (pos == 0) {
+ dst[pos] = '0';
+ pos++;
+ }
+
+ dst[pos] = '\0';
+}
+
+void arm_ulonglong2hexstr(char *dst, unsigned long long src)
+{
+ int ite, pos = 0;
+ static const char hexchars[] = "0123456789ABCDEF";
+
+ for (ite = 0; ite < 16; ite++) {
+ if ((pos == 0) && !((src >> (4 * (16 - ite - 1))) & 0xF)) {
+ continue;
+ }
+ dst[pos] = hexchars[(src >> (4 * (16 - ite - 1))) & 0xF];
+ pos++;
+ }
+
+ if (pos == 0) {
+ dst[pos] = '0';
+ pos++;
+ }
+
+ dst[pos] = '\0';
+}
+
diff --git a/tests/arm64/common/basic/arm_string.h b/tests/arm64/common/basic/arm_string.h
new file mode 100644
index 0000000..ea391ad
--- /dev/null
+++ b/tests/arm64/common/basic/arm_string.h
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_string.h
+ * @brief Header file for common string functions
+ */
+
+#ifndef __ARM_STRING_H_
+#define __ARM_STRING_H_
+
+#include <arm_types.h>
+
+void *arm_memcpy(void *dest, const void *src, unsigned int count);
+void *arm_memmove(void *dest, const void *src, unsigned int count);
+void *arm_memset(void *dest, int c, unsigned int count);
+int arm_memcmp(const void *s1, const void *s2, unsigned int count);
+char *arm_memchr(const char *p, int ch, int count);
+char *arm_strchr(const char *p, int ch);
+char *arm_strcpy(char *dest, const char *src);
+char *arm_strcat(char *dest, const char *src);
+int arm_strcmp(const char *a, const char *b);
+size_t arm_strlen(const char *s);
+int arm_str2int(char * src);
+void arm_int2str(char * dst, int src);
+void arm_ulonglong2str(char * dst, unsigned long long src);
+unsigned int arm_hexstr2uint(char * src);
+unsigned long long arm_hexstr2ulonglong(char * src);
+void arm_uint2hexstr(char * dst, unsigned int src);
+void arm_ulonglong2hexstr(char * dst, unsigned long long src);
+
+#endif /* __ARM_STRING_H_ */
diff --git a/tests/arm64/common/basic/arm_types.h b/tests/arm64/common/basic/arm_types.h
new file mode 100644
index 0000000..b266fd0
--- /dev/null
+++ b/tests/arm64/common/basic/arm_types.h
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2010 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_types.h
+ * @brief common header file for typedefs
+ */
+#ifndef _ARM_TYPES_H__
+#define _ARM_TYPES_H__
+
+typedef char s8;
+typedef short s16;
+typedef int s32;
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned int size_t;
+typedef unsigned int bool;
+typedef unsigned int ulong;
+
+/** Boolean macros */
+#define TRUE 1
+#define FALSE 0
+#define NULL ((void *)0)
+
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+
+typedef long long s64;
+typedef unsigned long long u64;
+typedef unsigned int irq_flags_t;
+typedef unsigned long virtual_addr_t;
+typedef unsigned long virtual_size_t;
+typedef unsigned long physical_addr_t;
+typedef unsigned long physical_size_t;
+
+typedef struct {
+ volatile long counter;
+} atomic_t;
+
+struct pt_regs {
+ u64 gpr[30]; /* X0 - X29 */
+ u64 lr;
+ u64 sp; /* Stack Pointer */
+ u64 pc; /* Program Counter */
+ u64 pstate; /* PState/SPSR */
+} __attribute ((packed)) ;
+
+#define _swab32(x) ((u32)( \
+ (((u32)(x) & (u32)0x000000ffU) << 24) | \
+ (((u32)(x) & (u32)0x0000ff00U) << 8) | \
+ (((u32)(x) & (u32)0x00ff0000U) >> 8) | \
+ (((u32)(x) & (u32)0xff000000U) >> 24)))
+
+#define _swab64(x) ((u64)( \
+ (((u64)(x) & (u64)0x00000000000000ffULL) << 56) | \
+ (((u64)(x) & (u64)0x000000000000ff00ULL) << 40) | \
+ (((u64)(x) & (u64)0x0000000000ff0000ULL) << 24) | \
+ (((u64)(x) & (u64)0x00000000ff000000ULL) << 8) | \
+ (((u64)(x) & (u64)0x000000ff00000000ULL) >> 8) | \
+ (((u64)(x) & (u64)0x0000ff0000000000ULL) >> 24) | \
+ (((u64)(x) & (u64)0x00ff000000000000ULL) >> 40) | \
+ (((u64)(x) & (u64)0xff00000000000000ULL) >> 56)))
+
+#define cpu_to_be32(x) _swab32(x)
+#define cpu_to_be64(x) _swab64(x)
+#define be32_to_cpu(x) _swab32(x)
+#define be64_to_cpu(x) _swab64(x)
+#define be32_to_cpup(x) _swab32(*(x))
+
+#define max(a,b) ((a) < (b) ? (b) : (a))
+
+#endif /* __ARM_TYPES_H__ */
diff --git a/tests/arm64/common/basic/dhry.h b/tests/arm64/common/basic/dhry.h
new file mode 100644
index 0000000..25f8f50
--- /dev/null
+++ b/tests/arm64/common/basic/dhry.h
@@ -0,0 +1,395 @@
+/*
+ ****************************************************************************
+ *
+ * "DHRYSTONE" Benchmark Program
+ * -----------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry.h (part 1 of 3)
+ *
+ * Date: May 25, 1988
+ *
+ * Updated By: Anup Patel (
an...@brainfault.org) for portablity.
+ *
+ * Author: Reinhold P. Weicker
+ * Siemens AG, E STE 35
+ * Postfach 3240
+ * 8520 Erlangen
+ * Germany (West)
+ * Phone: [xxx-49]-9131-7-20330
+ * (8-17 Central European Time)
+ * Usenet: ..!mcvax!unido!estevax!weicker
+ *
+ * Original Version (in Ada) published in
+ * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
+ * pp. 1013 - 1030, together with the statistics
+ * on which the distribution of statements etc. is based.
+ *
+ * In this C version, the following C library functions are used:
+ * - strcpy, strcmp (inside the measurement loop)
+ * - printf, scanf (outside the measurement loop)
+ * In addition, Berkeley UNIX system calls "times ()" or "time ()"
+ * are used for execution time measurement. For measurements
+ * on other systems, these calls have to be changed.
+ *
+ * Collection of Results:
+ * Reinhold Weicker (address see above) and
+ *
+ * Rick Richardson
+ * PC Research. Inc.
+ * 94 Apple Orchard Drive
+ * Tinton Falls, NJ 07724
+ * Phone:
(201) 389-8963 (9-17 EST)
+ * Usenet: ...!uunet!pcrat!rick
+ *
+ * Please send results to Rick Richardson and/or Reinhold Weicker.
+ * Complete information should be given on hardware and software used.
+ * Hardware information includes: Machine type, CPU, type and size
+ * of caches; for microprocessors: clock frequency, memory speed
+ * (number of wait states).
+ * Software information includes: Compiler (and runtime library)
+ * manufacturer and version, compilation switches, OS version.
+ * The Operating System version may give an indication about the
+ * compiler; Dhrystone itself performs no OS calls in the measurement loop.
+ *
+ * The complete output generated by the program should be mailed
+ * such that at least some checks for correctness can be made.
+ *
+ ***************************************************************************
+ *
+ * History: This version C/2.1 has been made for two reasons:
+ *
+ * 1) There is an obvious need for a common C version of
+ * Dhrystone, since C is at present the most popular system
+ * programming language for the class of processors
+ * (microcomputers, minicomputers) where Dhrystone is used most.
+ * There should be, as far as possible, only one C version of
+ * Dhrystone such that results can be compared without
+ * restrictions. In the past, the C versions distributed
+ * by Rick Richardson (Version 1.1) and by Reinhold Weicker
+ * had small (though not significant) differences.
+ *
+ * 2) As far as it is possible without changes to the Dhrystone
+ * statistics, optimizing compilers should be prevented from
+ * removing significant statements.
+ *
+ * This C version has been developed in cooperation with
+ * Rick Richardson (Tinton Falls, NJ), it incorporates many
+ * ideas from the "Version 1.1" distributed previously by
+ * him over the UNIX network Usenet.
+ * I also thank Chaim Benedelac (National Semiconductor),
+ * David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
+ * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
+ * for their help with comments on earlier versions of the
+ * benchmark.
+ *
+ * Changes: In the initialization part, this version follows mostly
+ * Rick Richardson's version distributed via Usenet, not the
+ * version distributed earlier via floppy disk by Reinhold Weicker.
+ * As a concession to older compilers, names have been made
+ * unique within the first 8 characters.
+ * Inside the measurement loop, this version follows the
+ * version previously distributed by Reinhold Weicker.
+ *
+ * At several places in the benchmark, code has been added,
+ * but within the measurement loop only in branches that
+ * are not executed. The intention is that optimizing compilers
+ * should be prevented from moving code out of the measurement
+ * loop, or from removing code altogether. Since the statements
+ * that are executed within the measurement loop have NOT been
+ * changed, the numbers defining the "Dhrystone distribution"
+ * (distribution of statements, operand types and locality)
+ * still hold. Except for sophisticated optimizing compilers,
+ * execution times for this version should be the same as
+ * for previous versions.
+ *
+ * Since it has proven difficult to subtract the time for the
+ * measurement loop overhead in a correct way, the loop check
+ * has been made a part of the benchmark. This does have
+ * an impact - though a very minor one - on the distribution
+ * statistics which have been updated for this version.
+ *
+ * All changes within the measurement loop are described
+ * and discussed in the companion paper "Rationale for
+ * Dhrystone version 2".
+ *
+ * Because of the self-imposed limitation that the order and
+ * distribution of the executed statements should not be
+ * changed, there are still cases where optimizing compilers
+ * may not generate code for some statements. To a certain
+ * degree, this is unavoidable for small synthetic benchmarks.
+ * Users of the benchmark are advised to check code listings
+ * whether code is generated for all statements of Dhrystone.
+ *
+ * Version 2.1 is identical to version 2.0 distributed via
+ * the UNIX network Usenet in March 1988 except that it corrects
+ * some minor deficiencies that were found by users of version 2.0.
+ * The only change within the measurement loop is that a
+ * non-executed "else" part was added to the "if" statement in
+ * Func_3, and a non-executed "else" part removed from Proc_3.
+ *
+ ***************************************************************************
+ *
+ * Defines: The following "Defines" are possible:
+ * -DREG=register (default: Not defined)
+ * As an approximation to what an average C programmer
+ * might do, the "register" storage class is applied
+ * (if enabled by -DREG=register)
+ * - for local variables, if they are used (dynamically)
+ * five or more times
+ * - for parameters if they are used (dynamically)
+ * six or more times
+ * Note that an optimal "register" strategy is
+ * compiler-dependent, and that "register" declarations
+ * do not necessarily lead to faster execution.
+ * -DNOSTRUCTASSIGN (default: Not defined)
+ * Define if the C compiler does not support
+ * assignment of structures.
+ * -DNOENUMS (default: Not defined)
+ * Define if the C compiler does not support
+ * enumeration types.
+ *
+ ***************************************************************************
+ *
+ * Compilation model and measurement (IMPORTANT):
+ *
+ * This C version of Dhrystone consists of three files:
+ * - dhry.h (this file, containing global definitions and comments)
+ * - dhry_1.c (containing the code corresponding to Ada package Pack_1)
+ * - dhry_2.c (containing the code corresponding to Ada package Pack_2)
+ *
+ * The following "ground rules" apply for measurements:
+ * - Separate compilation
+ * - No procedure merging
+ * - Otherwise, compiler optimizations are allowed but should be indicated
+ * - Default results are those without register declarations
+ * See the companion paper "Rationale for Dhrystone Version 2" for a more
+ * detailed discussion of these ground rules.
+ *
+ * For 16-Bit processors (e.g. 80186, 80286), times for all compilation
+ * models ("small", "medium", "large" etc.) should be given if possible,
+ * together with a definition of these models for the compiler system used.
+ *
+ **************************************************************************
+ *
+ * Dhrystone (C version) statistics:
+ *
+ * [Comment from the first distribution, updated for version 2.
+ * Note that because of language differences, the numbers are slightly
+ * different from the Ada version.]
+ *
+ * The following program contains statements of a high level programming
+ * language (here: C) in a distribution considered representative:
+ *
+ * assignments 52 (51.0 %)
+ * control statements 33 (32.4 %)
+ * procedure, function calls 17 (16.7 %)
+ *
+ * 103 statements are dynamically executed. The program is balanced with
+ * respect to the three aspects:
+ *
+ * - statement type
+ * - operand type
+ * - operand locality
+ * operand global, local, parameter, or constant.
+ *
+ * The combination of these three aspects is balanced only approximately.
+ *
+ * 1. Statement Type:
+ * ----------------- number
+ *
+ * V1 = V2 9
+ * (incl. V1 = F(..)
+ * V = Constant 12
+ * Assignment, 7
+ * with array element
+ * Assignment, 6
+ * with record component
+ * --
+ * 34 34
+ *
+ * X = Y +|-|"&&"|"|" Z 5
+ * X = Y +|-|"==" Constant 6
+ * X = X +|- 1 3
+ * X = Y *|/ Z 2
+ * X = Expression, 1
+ * two operators
+ * X = Expression, 1
+ * three operators
+ * --
+ * 18 18
+ *
+ * if .... 14
+ * with "else" 7
+ * without "else" 7
+ * executed 3
+ * not executed 4
+ * for ... 7 | counted every time
+ * while ... 4 | the loop condition
+ * do ... while 1 | is evaluated
+ * switch ... 1
+ * break 1
+ * declaration with 1
+ * initialization
+ * --
+ * 34 34
+ *
+ * P (...) procedure call 11
+ * user procedure 10
+ * library procedure 1
+ * X = F (...)
+ * function call 6
+ * user function 5
+ * library function 1
+ * --
+ * 17 17
+ * ---
+ * 103
+ *
+ * The average number of parameters in procedure or function calls
+ * is 1.82 (not counting the function values aX *
+ *
+ * 2. Operators
+ * ------------
+ * number approximate
+ * percentage
+ *
+ * Arithmetic 32 50.8
+ *
+ * + 21 33.3
+ * - 7 11.1
+ * * 3 4.8
+ * / (int div) 1 1.6
+ *
+ * Comparison 27 42.8
+ *
+ * == 9 14.3
+ * /= 4 6.3
+ * > 1 1.6
+ * < 3 4.8
+ * >= 1 1.6
+ * <= 9 14.3
+ *
+ * Logic 4 6.3
+ *
+ * && (AND-THEN) 1 1.6
+ * | (OR) 1 1.6
+ * ! (NOT) 2 3.2
+ *
+ * -- -----
+ * 63 100.1
+ *
+ *
+ * 3. Operand Type (counted once per operand reference):
+ * ---------------
+ * number approximate
+ * percentage
+ *
+ * Integer 175 72.3 %
+ * Character 45 18.6 %
+ * Pointer 12 5.0 %
+ * String30 6 2.5 %
+ * Array 2 0.8 %
+ * Record 2 0.8 %
+ * --- -------
+ * 242 100.0 %
+ *
+ * When there is an access path leading to the final operand (e.g. a record
+ * component), only the final data type on the access path is counted.
+ *
+ *
+ * 4. Operand Locality:
+ * -------------------
+ * number approximate
+ * percentage
+ *
+ * local variable 114 47.1 %
+ * global variable 22 9.1 %
+ * parameter 45 18.6 %
+ * value 23 9.5 %
+ * reference 22 9.1 %
+ * function result 6 2.5 %
+ * constant 55 22.7 %
+ * --- -------
+ * 242 100.0 %
+ *
+ *
+ * The program does not compute anything meaningful, but it is syntactically
+ * and semantically correct. All variables have a value assigned to them
+ * before they are used as a source operand.
+ *
+ * There has been no explicit effort to account for the effects of a
+ * cache, or to balance the use of long or short displacements for code or
+ * data.
+ *
+ ***************************************************************************
+ */
+
+#ifndef __DHRY_H_
+#define __DHRY_H_
+
+/* Compiler and system dependent definitions: */
+
+/* Berkeley UNIX C returns process times in seconds/HZ */
+
+#ifdef NOSTRUCTASSIGN
+#define structassign(d, s) memcpy(&(d), &(s), sizeof(d))
+#else
+#define structassign(d, s) d = s
+#endif
+
+#ifdef NOENUM
+#define Ident_1 0
+#define Ident_2 1
+#define Ident_3 2
+#define Ident_4 3
+#define Ident_5 4
+ typedef int Enumeration;
+#else
+ typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
+ Enumeration;
+#endif
+ /* for boolean and enumeration types in Ada, Pascal */
+
+/* General definitions: */
+
+ /* for strcpy, strcmp */
+
+#define Null 0
+ /* Value of a Null pointer */
+#define true 1
+#define false 0
+
+typedef int One_Thirty;
+typedef int One_Fifty;
+typedef char Capital_Letter;
+typedef int Boolean;
+typedef char Str_30 [31];
+typedef int Arr_1_Dim [50];
+typedef int Arr_2_Dim [50] [50];
+
+typedef struct record
+ {
+ struct record *Ptr_Comp;
+ Enumeration Discr;
+ union {
+ struct {
+ Enumeration Enum_Comp;
+ int Int_Comp;
+ char Str_Comp [31];
+ } var_1;
+ struct {
+ Enumeration E_Comp_2;
+ char Str_2_Comp [31];
+ } var_2;
+ struct {
+ char Ch_1_Comp;
+ char Ch_2_Comp;
+ } var_3;
+ } variant;
+ } Rec_Type, *Rec_Pointer;
+
+void dhry_main (int iterations);
+
+#endif /* __DHRY_H_ */
diff --git a/tests/arm64/common/basic/dhry_1.c b/tests/arm64/common/basic/dhry_1.c
new file mode 100644
index 0000000..7fff307
--- /dev/null
+++ b/tests/arm64/common/basic/dhry_1.c
@@ -0,0 +1,431 @@
+/*
+ ****************************************************************************
+ *
+ * "DHRYSTONE" Benchmark Program
+ * -----------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry_1.c (part 2 of 3)
+ *
+ * Date: May 25, 1988
+ *
+ * Updated By: Anup Patel (
an...@brainfault.org) for portablity.
+ *
+ * Author: Reinhold P. Weicker
+ *
+ ****************************************************************************
+ */
+
+#include "dhry.h"
+#include "dhry_port.h"
+
+/* Global Variables: */
+
+Rec_Pointer Ptr_Glob,
+ Next_Ptr_Glob;
+int Int_Glob;
+Boolean Bool_Glob;
+char Ch_1_Glob,
+ Ch_2_Glob;
+int Arr_1_Glob [50];
+int Arr_2_Glob [50] [50];
+
+
+#ifndef REG
+ Boolean Reg = false;
+#define REG
+ /* REG becomes defined as empty */
+ /* i.e. no register variables */
+#else
+ Boolean Reg = true;
+#endif
+
+TimeStamp Begin_Time,
+ End_Time,
+ User_Time;
+long Microseconds,
+ Dhrystones_Per_Second;
+
+/* end of variables for time measurement */
+
+/* forward declaration necessary */
+void Proc_1 (REG Rec_Pointer Ptr_Val_Par);
+void Proc_2 (One_Fifty *Int_Par_Ref);
+void Proc_3 (Rec_Pointer *Ptr_Ref_Par);
+void Proc_4 ();
+void Proc_5 ();
+void Proc_6 (Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par);
+void Proc_7 (One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref);
+void Proc_8 (Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val);
+Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
+Boolean Func_2 (Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref);
+
+
+void dhry_main (int iterations)
+/*****/
+
+ /* main program, corresponds to procedures */
+ /* Main and Proc_0 in the Ada version */
+{
+ One_Fifty Int_1_Loc;
+ REG One_Fifty Int_2_Loc;
+ One_Fifty Int_3_Loc;
+ REG char Ch_Index;
+ Enumeration Enum_Loc;
+ Str_30 Str_1_Loc;
+ Str_30 Str_2_Loc;
+ REG int Run_Index;
+ REG int Number_Of_Runs;
+
+ /* Initializations */
+ Number_Of_Runs = iterations;
+ Next_Ptr_Glob = (Rec_Pointer) dhry_malloc (sizeof (Rec_Type));
+ Ptr_Glob = (Rec_Pointer) dhry_malloc (sizeof (Rec_Type));
+
+ Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
+ Ptr_Glob->Discr = Ident_1;
+ Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
+ Ptr_Glob->variant.var_1.Int_Comp = 40;
+ dhry_strcpy (Ptr_Glob->variant.var_1.Str_Comp,
+ "DHRYSTONE PROGRAM, SOME STRING");
+ dhry_strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
+
+ Arr_2_Glob [8][7] = 10;
+ /* Was missing in published program. Without this statement, */
+ /* Arr_2_Glob [8][7] would have an undefined value. */
+ /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
+ /* overflow may occur for this array element. */
+
+ dhry_prints ("\n");
+ dhry_prints ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
+ dhry_prints ("\n");
+ if (Reg)
+ {
+ dhry_prints ("Program compiled with 'register' attribute\n");
+ dhry_prints ("\n");
+ }
+ else
+ {
+ dhry_prints ("Program compiled without 'register' attribute\n");
+ dhry_prints ("\n");
+ }
+
+ dhry_prints ("Execution starts, ");
+ dhry_printi (Number_Of_Runs);
+ dhry_prints (" runs through Dhrystone\n");
+
+ /***************/
+ /* Start timer */
+ /***************/
+
+ Begin_Time = dhry_timestamp();
+
+ for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
+ {
+
+ Proc_5();
+ Proc_4();
+ /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
+ Int_1_Loc = 2;
+ Int_2_Loc = 3;
+ dhry_strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
+ Enum_Loc = Ident_2;
+ Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
+ /* Bool_Glob == 1 */
+ while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
+ {
+ Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
+ /* Int_3_Loc == 7 */
+ Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
+ /* Int_3_Loc == 7 */
+ Int_1_Loc += 1;
+ } /* while */
+ /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
+ Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
+ /* Int_Glob == 5 */
+ Proc_1 (Ptr_Glob);
+ for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
+ /* loop body executed twice */
+ {
+ if (Enum_Loc == Func_1 (Ch_Index, 'C'))
+ /* then, not executed */
+ {
+ Proc_6 (Ident_1, &Enum_Loc);
+ dhry_strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
+ Int_2_Loc = Run_Index;
+ Int_Glob = Run_Index;
+ }
+ }
+ /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
+ Int_2_Loc = Int_2_Loc * Int_1_Loc;
+ Int_1_Loc = dhry_sdiv32(Int_2_Loc, Int_3_Loc);
+ Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
+ /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
+ Proc_2 (&Int_1_Loc);
+ /* Int_1_Loc == 5 */
+
+ } /* loop "for Run_Index" */
+
+ /**************/
+ /* Stop timer */
+ /**************/
+
+ End_Time = dhry_timestamp();
+
+ dhry_prints ("Execution ends\n");
+ dhry_prints ("\n");
+ dhry_prints ("Final values of the variables used in the benchmark:\n");
+ dhry_prints ("\n");
+ dhry_prints ("Int_Glob: ");
+ dhry_printi (Int_Glob);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (5);
+ dhry_prints ("\n");
+ dhry_prints ("Bool_Glob: ");
+ dhry_printi (Bool_Glob);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (1);
+ dhry_prints ("\n");
+ dhry_prints ("Ch_1_Glob: ");
+ dhry_printc (Ch_1_Glob);
+ dhry_prints ("\n");
+ dhry_prints (" should be: A\n");
+ dhry_prints ("Ch_2_Glob: ");
+ dhry_printc (Ch_2_Glob);
+ dhry_prints ("\n");
+ dhry_prints (" should be: B\n");
+ dhry_prints ("Arr_1_Glob[8]: ");
+ dhry_printi (Arr_1_Glob[8]);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (7);
+ dhry_prints ("\n");
+ dhry_prints ("Arr_2_Glob[8][7]: ");
+ dhry_printi (Arr_2_Glob[8][7]);
+ dhry_prints ("\n");
+ dhry_prints (" should be: Number_Of_Runs + 10\n");
+ dhry_prints ("Ptr_Glob->\n");
+ dhry_prints (" Ptr_Comp: ");
+ dhry_printll ((unsigned long long) Ptr_Glob->Ptr_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: (implementation-dependent)\n");
+ dhry_prints (" Discr: ");
+ dhry_printi (Ptr_Glob->Discr);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (0);
+ dhry_prints ("\n");
+ dhry_prints (" Enum_Comp: ");
+ dhry_printi (Ptr_Glob->variant.var_1.Enum_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (2);
+ dhry_prints ("\n");
+ dhry_prints (" Int_Comp: ");
+ dhry_printi (Ptr_Glob->variant.var_1.Int_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (17);
+ dhry_prints ("\n");
+ dhry_prints (" Str_Comp: ");
+ dhry_prints (Ptr_Glob->variant.var_1.Str_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
+ dhry_prints ("Next_Ptr_Glob->\n");
+ dhry_prints (" Ptr_Comp: ");
+ dhry_printll ((unsigned long long) Next_Ptr_Glob->Ptr_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: (implementation-dependent), same as above\n");
+ dhry_prints (" Discr: ");
+ dhry_printi (Next_Ptr_Glob->Discr);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (0);
+ dhry_prints ("\n");
+ dhry_prints (" Enum_Comp: ");
+ dhry_printi (Next_Ptr_Glob->variant.var_1.Enum_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (1);
+ dhry_prints ("\n");
+ dhry_prints (" Int_Comp: ");
+ dhry_printi (Next_Ptr_Glob->variant.var_1.Int_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (18);
+ dhry_prints ("\n");
+ dhry_prints (" Str_Comp: ");
+ dhry_prints (Next_Ptr_Glob->variant.var_1.Str_Comp);
+ dhry_prints ("\n");
+ dhry_prints (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
+ dhry_prints ("Int_1_Loc: ");
+ dhry_printi (Int_1_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (5);
+ dhry_prints ("\n");
+ dhry_prints ("Int_2_Loc: ");
+ dhry_printi (Int_2_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (13);
+ dhry_prints ("\n");
+ dhry_prints ("Int_3_Loc: ");
+ dhry_printi (Int_3_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (7);
+ dhry_prints ("\n");
+ dhry_prints ("Enum_Loc: ");
+ dhry_printi (Enum_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: ");
+ dhry_printi (1);
+ dhry_prints ("\n");
+ dhry_prints ("Str_1_Loc: ");
+ dhry_prints (Str_1_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
+ dhry_prints ("Str_2_Loc: ");
+ dhry_prints (Str_2_Loc);
+ dhry_prints ("\n");
+ dhry_prints (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
+ dhry_prints ("\n");
+
+ User_Time = End_Time - Begin_Time;
+
+ if (User_Time < Too_Small_Time)
+ {
+ dhry_prints ("Measured time too small to obtain meaningful results\n");
+ dhry_prints ("Please increase number of runs\n");
+ dhry_prints ("\n");
+ }
+ else
+ {
+ Microseconds = dhry_to_microsecs(User_Time);
+ Dhrystones_Per_Second = dhry_iter_per_sec(User_Time, Number_Of_Runs);
+ dhry_prints ("Microseconds for one run through Dhrystone: ");
+ dhry_printi (Microseconds);
+ dhry_prints (" \n");
+ dhry_prints ("Dhrystones per Second: ");
+ dhry_printi (Dhrystones_Per_Second);
+ dhry_prints (" \n");
+ dhry_prints ("Dhrystones MIPS: ");
+ dhry_printi (arm_sdiv32(Dhrystones_Per_Second, 1757));
+ dhry_prints (" \n");
+ dhry_prints ("\n");
+ }
+
+}
+
+
+void Proc_1 (Ptr_Val_Par)
+/******************/
+
+REG Rec_Pointer Ptr_Val_Par;
+ /* executed once */
+{
+ REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
+ /* == Ptr_Glob_Next */
+ /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */
+ /* corresponds to "rename" in Ada, "with" in Pascal */
+
+ structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
+ Ptr_Val_Par->variant.var_1.Int_Comp = 5;
+ Next_Record->variant.var_1.Int_Comp
+ = Ptr_Val_Par->variant.var_1.Int_Comp;
+ Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
+ Proc_3 (&Next_Record->Ptr_Comp);
+ /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
+ == Ptr_Glob->Ptr_Comp */
+ if (Next_Record->Discr == Ident_1)
+ /* then, executed */
+ {
+ Next_Record->variant.var_1.Int_Comp = 6;
+ Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
+ &Next_Record->variant.var_1.Enum_Comp);
+ Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
+ Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
+ &Next_Record->variant.var_1.Int_Comp);
+ }
+ else /* not executed */
+ structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
+} /* Proc_1 */
+
+
+void Proc_2 (Int_Par_Ref)
+/******************/
+ /* executed once */
+ /* *Int_Par_Ref == 1, becomes 4 */
+
+One_Fifty *Int_Par_Ref;
+{
+ One_Fifty Int_Loc;
+ Enumeration Enum_Loc;
+
+ Int_Loc = *Int_Par_Ref + 10;
+ do /* executed once */
+ if (Ch_1_Glob == 'A')
+ /* then, executed */
+ {
+ Int_Loc -= 1;
+ *Int_Par_Ref = Int_Loc - Int_Glob;
+ Enum_Loc = Ident_1;
+ } /* if */
+ while (Enum_Loc != Ident_1); /* true */
+} /* Proc_2 */
+
+
+void Proc_3 (Ptr_Ref_Par)
+/******************/
+ /* executed once */
+ /* Ptr_Ref_Par becomes Ptr_Glob */
+
+Rec_Pointer *Ptr_Ref_Par;
+
+{
+ if (Ptr_Glob != Null)
+ /* then, executed */
+ *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
+ Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
+} /* Proc_3 */
+
+
+void Proc_4 () /* without parameters */
+/*******/
+ /* executed once */
+{
+ Boolean Bool_Loc;
+
+ Bool_Loc = Ch_1_Glob == 'A';
+ Bool_Glob = Bool_Loc | Bool_Glob;
+ Ch_2_Glob = 'B';
+} /* Proc_4 */
+
+
+void Proc_5 () /* without parameters */
+/*******/
+ /* executed once */
+{
+ Ch_1_Glob = 'A';
+ Bool_Glob = false;
+} /* Proc_5 */
+
+
+ /* Procedure for the assignment of structures, */
+ /* if the C compiler doesn't support this feature */
+#ifdef NOSTRUCTASSIGN
+memcpy (d, s, l)
+register char *d;
+register char *s;
+register int l;
+{
+ while (l--) *d++ = *s++;
+}
+#endif
+
+
+
diff --git a/tests/arm64/common/basic/dhry_2.c b/tests/arm64/common/basic/dhry_2.c
new file mode 100644
index 0000000..8063db9
--- /dev/null
+++ b/tests/arm64/common/basic/dhry_2.c
@@ -0,0 +1,197 @@
+/*
+ ****************************************************************************
+ *
+ * "DHRYSTONE" Benchmark Program
+ * -----------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry_2.c (part 3 of 3)
+ *
+ * Date: May 25, 1988
+ *
+ * Author: Reinhold P. Weicker
+ *
+ ****************************************************************************
+ */
+
+#include "dhry.h"
+#include "dhry_port.h"
+
+#ifndef REG
+#define REG
+ /* REG becomes defined as empty */
+ /* i.e. no register variables */
+#endif
+
+extern int Int_Glob;
+extern char Ch_1_Glob;
+
+/* forward declaration necessary */
+Boolean Func_3 (Enumeration Enum_Par_Val);
+
+
+void Proc_6 (Enum_Val_Par, Enum_Ref_Par)
+/*********************************/
+ /* executed once */
+ /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
+
+Enumeration Enum_Val_Par;
+Enumeration *Enum_Ref_Par;
+{
+ *Enum_Ref_Par = Enum_Val_Par;
+ if (! Func_3 (Enum_Val_Par))
+ /* then, not executed */
+ *Enum_Ref_Par = Ident_4;
+ switch (Enum_Val_Par)
+ {
+ case Ident_1:
+ *Enum_Ref_Par = Ident_1;
+ break;
+ case Ident_2:
+ if (Int_Glob > 100)
+ /* then */
+ *Enum_Ref_Par = Ident_1;
+ else *Enum_Ref_Par = Ident_4;
+ break;
+ case Ident_3: /* executed */
+ *Enum_Ref_Par = Ident_2;
+ break;
+ case Ident_4: break;
+ case Ident_5:
+ *Enum_Ref_Par = Ident_3;
+ break;
+ } /* switch */
+} /* Proc_6 */
+
+
+void Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref)
+/**********************************************/
+ /* executed three times */
+ /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */
+ /* Int_Par_Ref becomes 7 */
+ /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
+ /* Int_Par_Ref becomes 17 */
+ /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
+ /* Int_Par_Ref becomes 18 */
+One_Fifty Int_1_Par_Val;
+One_Fifty Int_2_Par_Val;
+One_Fifty *Int_Par_Ref;
+{
+ One_Fifty Int_Loc;
+
+ Int_Loc = Int_1_Par_Val + 2;
+ *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
+} /* Proc_7 */
+
+
+void Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val)
+/*********************************************************************/
+ /* executed once */
+ /* Int_Par_Val_1 == 3 */
+ /* Int_Par_Val_2 == 7 */
+Arr_1_Dim Arr_1_Par_Ref;
+Arr_2_Dim Arr_2_Par_Ref;
+int Int_1_Par_Val;
+int Int_2_Par_Val;
+{
+ REG One_Fifty Int_Index;
+ REG One_Fifty Int_Loc;
+
+ Int_Loc = Int_1_Par_Val + 5;
+ Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
+ Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
+ Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
+ for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
+ Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
+ Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
+ Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
+ Int_Glob = 5;
+} /* Proc_8 */
+
+
+Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val)
+/*************************************************/
+ /* executed three times */
+ /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */
+ /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */
+ /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */
+
+Capital_Letter Ch_1_Par_Val;
+Capital_Letter Ch_2_Par_Val;
+{
+ Capital_Letter Ch_1_Loc;
+ Capital_Letter Ch_2_Loc;
+
+ Ch_1_Loc = Ch_1_Par_Val;
+ Ch_2_Loc = Ch_1_Loc;
+ if (Ch_2_Loc != Ch_2_Par_Val)
+ /* then, executed */
+ return (Ident_1);
+ else /* not executed */
+ {
+ Ch_1_Glob = Ch_1_Loc;
+ return (Ident_2);
+ }
+} /* Func_1 */
+
+
+Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref)
+/*************************************************/
+ /* executed once */
+ /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
+ /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
+
+Str_30 Str_1_Par_Ref;
+Str_30 Str_2_Par_Ref;
+{
+ REG One_Thirty Int_Loc;
+ Capital_Letter Ch_Loc;
+
+ Int_Loc = 2;
+ while (Int_Loc <= 2) /* loop body executed once */
+ if (Func_1 (Str_1_Par_Ref[Int_Loc],
+ Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
+ /* then, executed */
+ {
+ Ch_Loc = 'A';
+ Int_Loc += 1;
+ } /* if, while */
+ if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
+ /* then, not executed */
+ Int_Loc = 7;
+ if (Ch_Loc == 'R')
+ /* then, not executed */
+ return (true);
+ else /* executed */
+ {
+ if (dhry_strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
+ /* then, not executed */
+ {
+ Int_Loc += 7;
+ Int_Glob = Int_Loc;
+ return (true);
+ }
+ else /* executed */
+ return (false);
+ } /* if Ch_Loc */
+} /* Func_2 */
+
+
+Boolean Func_3 (Enum_Par_Val)
+/***************************/
+ /* executed once */
+ /* Enum_Par_Val == Ident_3 */
+Enumeration Enum_Par_Val;
+{
+ Enumeration Enum_Loc;
+
+ Enum_Loc = Enum_Par_Val;
+ if (Enum_Loc == Ident_3)
+ /* then, executed */
+ return (true);
+ else /* not executed */
+ return (false);
+} /* Func_3 */
+
+
diff --git a/tests/arm64/common/basic/dhry_port.c b/tests/arm64/common/basic/dhry_port.c
new file mode 100644
index 0000000..946c27e
--- /dev/null
+++ b/tests/arm64/common/basic/dhry_port.c
@@ -0,0 +1,83 @@
+/*
+ ****************************************************************************
+ *
+ * "DHRYSTONE" Portability Section
+ * -------------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry_port.c (for portability)
+ *
+ * Date: Aug 15, 2011
+ *
+ * Author: Anup Patel (
an...@brainfault.org)
+ *
+ ****************************************************************************
+ */
+
+#include <arm_heap.h>
+#include <arm_stdio.h>
+#include <arm_string.h>
+#include <arm_board.h>
+#include "dhry_port.h"
+
+extern u8 _heap_start;
+
+void * dhry_malloc(unsigned int size)
+{
+ return arm_malloc(size);
+}
+
+TimeStamp dhry_timestamp(void)
+{
+ return arm_udiv64(arm_board_timer_timestamp(), 1000);
+}
+
+long dhry_to_microsecs(TimeStamp UserTime)
+{
+ return UserTime;
+}
+
+long dhry_iter_per_sec(TimeStamp UserTime, int Number_Of_Runs)
+{
+ return arm_udiv64(((TimeStamp)Number_Of_Runs * (TimeStamp)1000000),
+ UserTime);
+}
+
+int dhry_strcmp(char *dst, char *src)
+{
+ return arm_strcmp(dst, src);
+}
+
+void dhry_strcpy(char *dst, char *src)
+{
+ arm_strcpy(dst, src);
+}
+
+void dhry_printc(char ch)
+{
+ char tmp[2];
+ tmp[0] = ch;
+ tmp[1] = '\0';
+ arm_puts(tmp);
+}
+
+void dhry_prints(char *str)
+{
+ arm_puts(str);
+}
+
+void dhry_printi(int val)
+{
+ char tmp[128];
+ arm_int2str(tmp, val);
+ arm_puts(tmp);
+}
+
+void dhry_printll(unsigned long long val)
+{
+ char tmp[128];
+ arm_ulonglong2str(tmp, val);
+ arm_puts(tmp);
+}
+
diff --git a/tests/arm64/common/basic/dhry_port.h b/tests/arm64/common/basic/dhry_port.h
new file mode 100644
index 0000000..f21ccf4
--- /dev/null
+++ b/tests/arm64/common/basic/dhry_port.h
@@ -0,0 +1,42 @@
+/*
+ ****************************************************************************
+ *
+ * "DHRYSTONE" Portability Section
+ * -------------------------------
+ *
+ * Version: C, Version 2.1
+ *
+ * File: dhry_port.h (for portability)
+ *
+ * Date: Aug 15, 2011
+ *
+ * Author: Anup Patel (
an...@brainfault.org)
+ *
+ ****************************************************************************
+ */
+
+#ifndef __DHRY_PORT_H_
+#define __DHRY_PORT_H_
+
+#include <arm_math.h>
+
+#define REG register
+
+typedef unsigned long long TimeStamp;
+
+#define Too_Small_Time (TimeStamp)1000000
+
+#define dhry_sdiv32(v, d) arm_sdiv32((v), (d))
+
+void * dhry_malloc(unsigned int size);
+TimeStamp dhry_timestamp(void);
+long dhry_to_microsecs(TimeStamp UserTime);
+long dhry_iter_per_sec(TimeStamp UserTime, int Number_Of_Runs);
+int dhry_strcmp(char *dst, char *src);
+void dhry_strcpy(char *dst, char *src);
+void dhry_printc(char ch);
+void dhry_prints(char *str);
+void dhry_printi(int val);
+void dhry_printll(unsigned long long val);
+
+#endif /* __DHRY_PORT_H_ */
diff --git a/tests/arm64/common/basic/firmware.ld b/tests/arm64/common/basic/firmware.ld
new file mode 100755
index 0000000..2b201cd
--- /dev/null
+++ b/tests/arm64/common/basic/firmware.ld
@@ -0,0 +1,97 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file firmware.ld
+ * @brief Linker script for basic firmware
+ */
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH("aarch64")
+ENTRY(_start)
+
+SECTIONS
+{
+ . = TEXT_START;
+
+ PROVIDE(_code_start = .);
+ PROVIDE(_reloc_region_start = .);
+
+ .text :
+ {
+ *(.expvect)
+ *(.text)
+ _etext = .;
+ }
+
+ .data :
+ {
+ . = ALIGN(8);
+ *(.data)
+ _edata = .;
+ }
+
+ .rodata :
+ {
+ . = ALIGN(8);
+ *(.rodata .rodata.*)
+ _erodata = .;
+ }
+
+ PROVIDE(_reloc_region_end = .);
+
+ PROVIDE(_zero_region_start = .);
+
+ .bss :
+ {
+ . = ALIGN(8);
+ PROVIDE(_bss_start = .);
+ *(.bss)
+ _ebss = .;
+ PROVIDE(_bss_end = .);
+ }
+
+ .heap :
+ {
+ . = ALIGN(8);
+ PROVIDE(_heap_start = .);
+ *(.heap)
+ . = . + 4096;
+ PROVIDE(_heap_end = .);
+ }
+
+ PROVIDE(_zero_region_end = .);
+
+ .svc_stack :
+ {
+ PROVIDE(_svc_stack_start = .);
+ . = . + 4096;
+ . = ALIGN(8);
+ PROVIDE(_svc_stack_end = .);
+ }
+
+ .usr_stack :
+ {
+ PROVIDE(_usr_stack_start = .);
+ . = . + 4096;
+ . = ALIGN(8);
+ PROVIDE(_usr_stack_end = .);
+ }
+
+ PROVIDE(_code_end = .);
+}
diff --git a/tests/arm64/common/basic/libfdt/cmd_fdt.c b/tests/arm64/common/basic/libfdt/cmd_fdt.c
new file mode 100644
index 0000000..447febd
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/cmd_fdt.c
@@ -0,0 +1,443 @@
+/*
+ * (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS,
vanb...@cideas.com
+ * Based on code written by:
+ * Pantelis Antoniou <
pantelis...@gmail.com> and
+ * Matthew McClintock <
m...@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <arm_string.h>
+#include <arm_stdio.h>
+#include <ctype.h>
+#include <arm_types.h>
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+#include <libfdt/fdt_support.h>
+
+#define MAX_LEVEL 32 /* how deeply nested we will go */
+#define SCRATCHPAD 1024 /* bytes of scratchpad memory */
+
+//static int fdt_valid(void);
+//static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
+static int fdt_print(const char *pathp, char *prop, int depth);
+
+/*
+ * The working_fdt points to our working flattened device tree.
+ */
+struct fdt_header *working_fdt;
+
+#if 0
+static void usage(void)
+{
+ printf("Usage: fdt addr <addr> [<length>] - Set the fdt location to <addr>\n"
+ "fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active\n"
+ "fdt resize - Resize fdt to size + padding to 4k addr\n"
+ "fdt print <path> [<prop>] - Recursive print starting at <path>\n"
+ "fdt list <path> [<prop>] - Print one level starting at <path>\n"
+ "fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n"
+ "fdt mknode <path> <node> - Create a new node after <path>\n"
+ "fdt rm <path> [<prop>] - Delete the node or <property>\n"
+ "fdt header - Display header info\n"
+ "fdt bootcpu <id> - Set boot cpuid\n"
+ "fdt memory <addr> <size> - Add/Update memory node\n"
+ "fdt rsvmem print - Show current mem reserves\n"
+ "fdt rsvmem add <addr> <size> - Add a mem reserve\n"
+ "fdt rsvmem delete <index> - Delete a mem reserves\n"
+ "fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree\n"
+ " <start>/<end> - initrd start/end addr\n"
+ "NOTE: Dereference aliases by omiting the leading '/', "
+ "e.g. fdt print ethernet0.");
+}
+#endif
+
+void set_working_fdt_addr(void *addr)
+{
+ working_fdt = addr;
+}
+
+void dump_fdt(unsigned long fdt_addr)
+{
+ set_working_fdt_addr((void *)fdt_addr);
+ fdt_print("/", NULL, 32);
+}
+/****************************************************************************/
+
+#if 0
+static int fdt_valid(void)
+{
+ int err;
+
+ if (working_fdt == NULL) {
+ printf ("The address of the fdt is invalid (NULL).\n");
+ return 0;
+ }
+
+ err = fdt_check_header(working_fdt);
+ if (err == 0)
+ return 1; /* valid */
+
+ if (err < 0) {
+ printf("libfdt fdt_check_header(): %s", fdt_strerror(err));
+ /*
+ * Be more informative on bad version.
+ */
+ if (err == -FDT_ERR_BADVERSION) {
+ if (fdt_version(working_fdt) <
+ FDT_FIRST_SUPPORTED_VERSION) {
+ printf (" - too old, fdt %d < %d",
+ fdt_version(working_fdt),
+ FDT_FIRST_SUPPORTED_VERSION);
+ working_fdt = NULL;
+ }
+ if (fdt_last_comp_version(working_fdt) >
+ FDT_LAST_SUPPORTED_VERSION) {
+ printf (" - too new, fdt %d > %d",
+ fdt_version(working_fdt),
+ FDT_LAST_SUPPORTED_VERSION);
+ working_fdt = NULL;
+ }
+ return 0;
+ }
+ printf("\n");
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+/****************************************************************************/
+
+#if 0
+/*
+ * Parse the user's input, partially heuristic. Valid formats:
+ * <0x00112233 4 05> - an array of cells. Numbers follow standard
+ * C conventions.
+ * [00 11 22 .. nn] - byte stream
+ * "string" - If the the value doesn't start with "<" or "[", it is
+ * treated as a string. Note that the quotes are
+ * stripped by the parser before we get the string.
+ * newval: An array of strings containing the new property as specified
+ * on the command line
+ * count: The number of strings in the array
+ * data: A bytestream to be placed in the property
+ * len: The length of the resulting bytestream
+ */
+static int fdt_parse_prop(char * const *newval, int count, char *data, int *len)
+{
+ char *cp; /* temporary char pointer */
+ char *newp; /* temporary newval char pointer */
+ unsigned long tmp; /* holds converted values */
+ int stridx = 0;
+
+ *len = 0;
+ newp = newval[0];
+
+ /* An array of cells */
+ if (*newp == '<') {
+ newp++;
+ while ((*newp != '>') && (stridx < count)) {
+ /*
+ * Keep searching until we find that last ">"
+ * That way users don't have to escape the spaces
+ */
+ if (*newp == '\0') {
+ newp = newval[++stridx];
+ continue;
+ }
+
+ cp = newp;
+ strtoul(cp, &newp, 0, &tmp);
+ *(u32 *)data = cpu_to_be32(tmp);
+ data += 4;
+ *len += 4;
+
+ /* If the ptr didn't advance, something went wrong */
+ if ((newp - cp) <= 0) {
+ printf("Sorry, I could not convert \"%s\"\n",
+ cp);
+ return 1;
+ }
+
+ while (*newp == ' ')
+ newp++;
+ }
+
+ if (*newp != '>') {
+ printf("Unexpected character '%c'\n", *newp);
+ return 1;
+ }
+ } else if (*newp == '[') {
+ /*
+ * Byte stream. Convert the values.
+ */
+ newp++;
+ while ((stridx < count) && (*newp != ']')) {
+ while (*newp == ' ')
+ newp++;
+ if (*newp == '\0') {
+ newp = newval[++stridx];
+ continue;
+ }
+ if (!isxdigit(*newp))
+ break;
+ strtoul(newp, &newp, 0, &tmp);
+ *data++ = tmp & 0xFF;
+ *len = *len + 1;
+ }
+ if (*newp != ']') {
+ printf("Unexpected character '%c'\n", *newp);
+ return 1;
+ }
+ } else {
+ /*
+ * Assume it is one or more strings. Copy it into our
+ * data area for convenience (including the
+ * terminating '\0's).
+ */
+ while (stridx < count) {
+ size_t length = strlen(newp) + 1;
+ strcpy(data, newp);
+ data += length;
+ *len += length;
+ newp = newval[++stridx];
+ }
+ }
+ return 0;
+}
+#endif
+
+/****************************************************************************/
+
+/*
+ * Heuristic to guess if this is a string or concatenated strings.
+ */
+
+#define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up)
+#define arm_isprint(c) in_range(c, 0x20, 0x7f)
+
+static int is_printable_string(const void *data, int len)
+{
+ const char *s = data;
+
+ /* zero length is not */
+ if (len == 0)
+ return 0;
+
+ /* must terminate with zero */
+ if (s[len - 1] != '\0')
+ return 0;
+
+ /* printable or a null byte (concatenated strings) */
+ while (((*s == '\0') || arm_isprint(*s)) && (len > 0)) {
+ /*
+ * If we see a null, there are three possibilities:
+ * 1) If len == 1, it is the end of the string, printable
+ * 2) Next character also a null, not printable.
+ * 3) Next character not a null, continue to check.
+ */
+ if (s[0] == '\0') {
+ if (len == 1)
+ return 1;
+ if (s[1] == '\0')
+ return 0;
+ }
+ s++;
+ len--;
+ }
+
+ /* Not the null termination, or not done yet: not printable */
+ if (*s != '\0' || (len != 0))
+ return 0;
+
+ return 1;
+}
+
+
+/*
+ * Print the property in the best format, a heuristic guess. Print as
+ * a string, concatenated strings, a byte, word, double word, or (if all
+ * else fails) it is printed as a stream of bytes.
+ */
+static void print_data(const void *data, int len)
+{
+ int j;
+
+ /* no data, don't print */
+ if (len == 0)
+ return;
+
+ /*
+ * It is a string, but it may have multiple strings (embedded '\0's).
+ */
+ if (is_printable_string(data, len)) {
+ printf("\"");
+ j = 0;
+ while (j < len) {
+ if (j > 0)
+ printf("\", \"");
+ printf(data);
+ j += strlen(data) + 1;
+ data += strlen(data) + 1;
+ }
+ printf("\"");
+ return;
+ }
+
+ if ((len %4) == 0) {
+ const u32 *p;
+
+ printf("<");
+ for (j = 0, p = data; j < len/4; j ++)
+ printf("0x%x%s", fdt32_to_cpu(p[j]), j < (len/4 - 1) ? " " : "");
+ printf(">");
+ } else { /* anything else... hexdump */
+ const u8 *s;
+
+ printf("[");
+ for (j = 0, s = data; j < len; j++)
+ printf("%02x%s", s[j], j < len - 1 ? " " : "");
+ printf("]");
+ }
+}
+
+/****************************************************************************/
+
+/*
+ * Recursively print (a portion of) the working_fdt. The depth parameter
+ * determines how deeply nested the fdt is printed.
+ */
+static int fdt_print(const char *pathp, char *prop, int depth)
+{
+ static char tabs[MAX_LEVEL+1] =
+ "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
+ "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+ const void *nodep; /* property node pointer */
+ int nodeoffset; /* node offset from libfdt */
+ int nextoffset; /* next node offset from libfdt */
+ u32 tag; /* tag */
+ int len; /* length of the property */
+ int level = 0; /* keep track of nesting level */
+ const struct fdt_property *fdt_prop;
+
+ nodeoffset = fdt_path_offset (working_fdt, pathp);
+ if (nodeoffset < 0) {
+ /*
+ * Not found or something else bad happened.
+ */
+ printf ("libfdt fdt_path_offset() returned %s\n",
+ fdt_strerror(nodeoffset));
+ return 1;
+ }
+ /*
+ * The user passed in a property as well as node path.
+ * Print only the given property and then return.
+ */
+ if (prop) {
+ nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len);
+ if (len == 0) {
+ /* no property value */
+ printf("%s %s\n", pathp, prop);
+ return 0;
+ } else if (len > 0) {
+ printf("%s = ", prop);
+ print_data (nodep, len);
+ printf("\n");
+ return 0;
+ } else {
+ printf ("libfdt fdt_getprop(): %s\n",
+ fdt_strerror(len));
+ return 1;
+ }
+ }
+
+ /*
+ * The user passed in a node path and no property,
+ * print the node and all subnodes.
+ */
+ while(level >= 0) {
+ tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
+ switch(tag) {
+ case FDT_BEGIN_NODE:
+ pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
+ if (level <= depth) {
+ if (pathp == NULL)
+ pathp = "/* NULL pointer error */";
+ if (*pathp == '\0')
+ pathp = "/"; /* root is nameless */
+ printf("%s%s {\n",
+ &tabs[MAX_LEVEL - level], pathp);
+ }
+ level++;
+ if (level >= MAX_LEVEL) {
+ printf("Nested too deep, aborting.\n");
+ return 1;
+ }
+ break;
+ case FDT_END_NODE:
+ level--;
+ if (level <= depth)
+ printf("%s};\n", &tabs[MAX_LEVEL - level]);
+ if (level == 0) {
+ level = -1; /* exit the loop */
+ }
+ break;
+ case FDT_PROP:
+ fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
+ sizeof(*fdt_prop));
+ pathp = fdt_string(working_fdt,
+ fdt32_to_cpu(fdt_prop->nameoff));
+ len = fdt32_to_cpu(fdt_prop->len);
+ nodep = fdt_prop->data;
+ if (len < 0) {
+ printf ("libfdt fdt_getprop(): %s\n",
+ fdt_strerror(len));
+ return 1;
+ } else if (len == 0) {
+ /* the property has no value */
+ if (level <= depth)
+ printf("%s%s;\n",
+ &tabs[MAX_LEVEL - level],
+ pathp);
+ } else {
+ if (level <= depth) {
+ printf("%s%s = ",
+ &tabs[MAX_LEVEL - level],
+ pathp);
+ print_data (nodep, len);
+ printf(";\n");
+ }
+ }
+ break;
+ case FDT_NOP:
+ printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]);
+ break;
+ case FDT_END:
+ return 1;
+ default:
+ if (level <= depth)
+ printf("Unknown tag 0x%08X\n", tag);
+ return 1;
+ }
+ nodeoffset = nextoffset;
+ }
+ return 0;
+}
+
diff --git a/tests/arm64/common/basic/libfdt/fdt.c b/tests/arm64/common/basic/libfdt/fdt.c
new file mode 100644
index 0000000..a160ef9
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt.c
@@ -0,0 +1,222 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_check_header(const void *fdt)
+{
+ if (fdt_magic(fdt) == FDT_MAGIC) {
+ /* Complete tree */
+ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+ /* Unfinished sequential-write blob */
+ if (fdt_size_dt_struct(fdt) == 0)
+ return -FDT_ERR_BADSTATE;
+ } else {
+ return -FDT_ERR_BADMAGIC;
+ }
+
+ return 0;
+}
+
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
+{
+ const char *p;
+
+ if (fdt_version(fdt) >= 0x11)
+ if (((offset + len) < offset)
+ || ((offset + len) > fdt_size_dt_struct(fdt)))
+ return NULL;
+
+ p = _fdt_offset_ptr(fdt, offset);
+
+ if (p + len < p)
+ return NULL;
+ return p;
+}
+
+u32 fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
+{
+ const u32 *tagp, *lenp;
+ u32 tag;
+ int offset = startoffset;
+ const char *p;
+
+ *nextoffset = -FDT_ERR_TRUNCATED;
+ tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
+ if (!tagp)
+ return FDT_END; /* premature end */
+ tag = fdt32_to_cpu(*tagp);
+ offset += FDT_TAGSIZE;
+
+ *nextoffset = -FDT_ERR_BADSTRUCTURE;
+ switch (tag) {
+ case FDT_BEGIN_NODE:
+ /* skip name */
+ do {
+ p = fdt_offset_ptr(fdt, offset++, 1);
+ } while (p && (*p != '\0'));
+ if (!p)
+ return FDT_END; /* premature end */
+ break;
+
+ case FDT_PROP:
+ lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
+ if (!lenp)
+ return FDT_END; /* premature end */
+ /* skip-name offset, length and value */
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ + fdt32_to_cpu(*lenp);
+ break;
+
+ case FDT_END:
+ case FDT_END_NODE:
+ case FDT_NOP:
+ break;
+
+ default:
+ return FDT_END;
+ }
+
+ if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+ return FDT_END; /* premature end */
+
+ *nextoffset = FDT_TAGALIGN(offset);
+ return tag;
+}
+
+int _fdt_check_node_offset(const void *fdt, int offset)
+{
+ if ((offset < 0) || (offset % FDT_TAGSIZE)
+ || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
+ return -FDT_ERR_BADOFFSET;
+
+ return offset;
+}
+
+int _fdt_check_prop_offset(const void *fdt, int offset)
+{
+ if ((offset < 0) || (offset % FDT_TAGSIZE)
+ || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+ return -FDT_ERR_BADOFFSET;
+
+ return offset;
+}
+
+int fdt_next_node(const void *fdt, int offset, int *depth)
+{
+ int nextoffset = 0;
+ u32 tag;
+
+ if (offset >= 0)
+ if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
+ return nextoffset;
+
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_PROP:
+ case FDT_NOP:
+ break;
+
+ case FDT_BEGIN_NODE:
+ if (depth)
+ (*depth)++;
+ break;
+
+ case FDT_END_NODE:
+ if (depth && ((--(*depth)) < 0))
+ return nextoffset;
+ break;
+
+ case FDT_END:
+ if ((nextoffset >= 0)
+ || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+ return -FDT_ERR_NOTFOUND;
+ else
+ return nextoffset;
+ }
+ } while (tag != FDT_BEGIN_NODE);
+
+ return offset;
+}
+
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
+{
+ int len = strlen(s) + 1;
+ const char *last = strtab + tabsize - len;
+ const char *p;
+
+ for (p = strtab; p <= last; p++)
+ if (memcmp(p, s, len) == 0)
+ return p;
+ return NULL;
+}
+
+int fdt_move(const void *fdt, void *buf, int bufsize)
+{
+ FDT_CHECK_HEADER(fdt);
+
+ if (fdt_totalsize(fdt) > bufsize)
+ return -FDT_ERR_NOSPACE;
+
+ memmove(buf, fdt, fdt_totalsize(fdt));
+ return 0;
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt.h b/tests/arm64/common/basic/libfdt/fdt.h
new file mode 100644
index 0000000..2a0552c
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt.h
@@ -0,0 +1,62 @@
+#ifndef _FDT_H
+#define _FDT_H
+
+#ifndef __ASSEMBLY__
+
+struct fdt_header {
+ u32 magic; /* magic word FDT_MAGIC */
+ u32 totalsize; /* total size of DT block */
+ u32 off_dt_struct; /* offset to structure */
+ u32 off_dt_strings; /* offset to strings */
+ u32 off_mem_rsvmap; /* offset to memory reserve map */
+ u32 version; /* format version */
+ u32 last_comp_version; /* last compatible version */
+
+ /* version 2 fields below */
+ u32 boot_cpuid_phys; /* Which physical CPU id we're
+ booting on */
+ /* version 3 fields below */
+ u32 size_dt_strings; /* size of the strings block */
+
+ /* version 17 fields below */
+ u32 size_dt_struct; /* size of the structure block */
+};
+
+struct fdt_reserve_entry {
+ u64 address;
+ u64 size;
+};
+
+struct fdt_node_header {
+ u32 tag;
+ char name[0];
+};
+
+struct fdt_property {
+ u32 tag;
+ u32 len;
+ u32 nameoff;
+ char data[0];
+};
+
+#endif /* !__ASSEMBLY */
+
+#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
+#define FDT_TAGSIZE sizeof(u32)
+
+#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
+#define FDT_END_NODE 0x2 /* End node */
+#define FDT_PROP 0x3 /* Property: name off,
+ size, content */
+#define FDT_NOP 0x4 /* nop */
+#define FDT_END 0x9
+
+#define FDT_V1_SIZE (7*sizeof(u32))
+#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(u32))
+#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(u32))
+#define FDT_V16_SIZE FDT_V3_SIZE
+#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(u32))
+
+/* adding a ramdisk needs 0x44 bytes in version 2008.10 */
+#define FDT_RAMDISK_OVERHEAD 0x80
+#endif /* _FDT_H */
diff --git a/tests/arm64/common/basic/libfdt/fdt_ro.c b/tests/arm64/common/basic/libfdt/fdt_ro.c
new file mode 100644
index 0000000..0b1f934
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_ro.c
@@ -0,0 +1,574 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_nodename_eq(const void *fdt, int offset,
+ const char *s, int len)
+{
+ const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
+
+ if (! p)
+ /* short match */
+ return 0;
+
+ if (memcmp(p, s, len) != 0)
+ return 0;
+
+ if (p[len] == '\0')
+ return 1;
+ else if (!memchr(s, '@', len) && (p[len] == '@'))
+ return 1;
+ else
+ return 0;
+}
+
+const char *fdt_string(const void *fdt, int stroffset)
+{
+ return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+}
+
+static int _fdt_string_eq(const void *fdt, int stroffset,
+ const char *s, int len)
+{
+ const char *p = fdt_string(fdt, stroffset);
+
+ return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+}
+
+int fdt_get_mem_rsv(const void *fdt, int n, u64 *address, u64 *size)
+{
+ FDT_CHECK_HEADER(fdt);
+ *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
+ *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
+ return 0;
+}
+
+int fdt_num_mem_rsv(const void *fdt)
+{
+ int i = 0;
+
+ while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
+ i++;
+ return i;
+}
+
+static int _nextprop(const void *fdt, int offset)
+{
+ u32 tag;
+ int nextoffset;
+
+ do {
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_END:
+ if (nextoffset >= 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ else
+ return nextoffset;
+
+ case FDT_PROP:
+ return offset;
+ }
+ offset = nextoffset;
+ } while (tag == FDT_NOP);
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_subnode_offset_namelen(const void *fdt, int offset,
+ const char *name, int namelen)
+{
+ int depth;
+
+ FDT_CHECK_HEADER(fdt);
+
+ for (depth = 0;
+ (offset >= 0) && (depth >= 0);
+ offset = fdt_next_node(fdt, offset, &depth))
+ if ((depth == 1)
+ && _fdt_nodename_eq(fdt, offset, name, namelen))
+ return offset;
+
+ if (depth < 0)
+ return -FDT_ERR_NOTFOUND;
+ return offset; /* error */
+}
+
+int fdt_subnode_offset(const void *fdt, int parentoffset,
+ const char *name)
+{
+ return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_path_offset(const void *fdt, const char *path)
+{
+ const char *end = path + strlen(path);
+ const char *p = path;
+ int offset = 0;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* see if we have an alias */
+ if (*path != '/') {
+ const char *q = strchr(path, '/');
+
+ if (!q)
+ q = end;
+
+ p = fdt_get_alias_namelen(fdt, p, q - p);
+ if (!p)
+ return -FDT_ERR_BADPATH;
+ offset = fdt_path_offset(fdt, p);
+
+ p = q;
+ }
+
+ while (*p) {
+ const char *q;
+
+ while (*p == '/')
+ p++;
+ if (! *p)
+ return offset;
+ q = strchr(p, '/');
+ if (! q)
+ q = end;
+
+ offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
+ if (offset < 0)
+ return offset;
+
+ p = q;
+ }
+
+ return offset;
+}
+
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
+{
+ const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
+ int err;
+
+ if (((err = fdt_check_header(fdt)) != 0)
+ || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+ goto fail;
+
+ if (len)
+ *len = strlen(nh->name);
+
+ return nh->name;
+
+ fail:
+ if (len)
+ *len = err;
+ return NULL;
+}
+
+int fdt_first_property_offset(const void *fdt, int nodeoffset)
+{
+ int offset;
+
+ if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ return offset;
+
+ return _nextprop(fdt, offset);
+}
+
+int fdt_next_property_offset(const void *fdt, int offset)
+{
+ if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+ return offset;
+
+ return _nextprop(fdt, offset);
+}
+
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp)
+{
+ int err;
+ const struct fdt_property *prop;
+
+ if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+ if (lenp)
+ *lenp = err;
+ return NULL;
+ }
+
+ prop = _fdt_offset_ptr(fdt, offset);
+
+ if (lenp)
+ *lenp = fdt32_to_cpu(prop->len);
+
+ return prop;
+}
+
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int offset,
+ const char *name,
+ int namelen, int *lenp)
+{
+ for (offset = fdt_first_property_offset(fdt, offset);
+ (offset >= 0);
+ (offset = fdt_next_property_offset(fdt, offset))) {
+ const struct fdt_property *prop;
+
+ if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
+ offset = -FDT_ERR_INTERNAL;
+ break;
+ }
+ if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+ name, namelen))
+ return prop;
+ }
+
+ if (lenp)
+ *lenp = offset;
+ return NULL;
+}
+
+const struct fdt_property *fdt_get_property(const void *fdt,
+ int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_get_property_namelen(fdt, nodeoffset, name,
+ strlen(name), lenp);
+}
+
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
+ if (! prop)
+ return NULL;
+
+ return prop->data;
+}
+
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+ const char **namep, int *lenp)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_by_offset(fdt, offset, lenp);
+ if (!prop)
+ return NULL;
+ if (namep)
+ *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ return prop->data;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
+u32 fdt_get_phandle(const void *fdt, int nodeoffset)
+{
+ const u32 *php;
+ int len;
+
+ /* FIXME: This is a bit sub-optimal, since we potentially scan
+ * over all the properties twice. */
+ php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+ if (!php || (len != sizeof(*php))) {
+ php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+ if (!php || (len != sizeof(*php)))
+ return 0;
+ }
+
+ return fdt32_to_cpu(*php);
+}
+
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen)
+{
+ int aliasoffset;
+
+ aliasoffset = fdt_path_offset(fdt, "/aliases");
+ if (aliasoffset < 0)
+ return NULL;
+
+ return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+ return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
+{
+ int pdepth = 0, p = 0;
+ int offset, depth, namelen;
+ const char *name;
+
+ FDT_CHECK_HEADER(fdt);
+
+ if (buflen < 2)
+ return -FDT_ERR_NOSPACE;
+
+ for (offset = 0, depth = 0;
+ (offset >= 0) && (offset <= nodeoffset);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ while (pdepth > depth) {
+ do {
+ p--;
+ } while (buf[p-1] != '/');
+ pdepth--;
+ }
+
+ if (pdepth >= depth) {
+ name = fdt_get_name(fdt, offset, &namelen);
+ if (!name)
+ return namelen;
+ if ((p + namelen + 1) <= buflen) {
+ memcpy(buf + p, name, namelen);
+ p += namelen;
+ buf[p++] = '/';
+ pdepth++;
+ }
+ }
+
+ if (offset == nodeoffset) {
+ if (pdepth < (depth + 1))
+ return -FDT_ERR_NOSPACE;
+
+ if (p > 1) /* special case so that root path is "/", not "" */
+ p--;
+ buf[p] = '\0';
+ return 0;
+ }
+ }
+
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+ int supernodedepth, int *nodedepth)
+{
+ int offset, depth;
+ int supernodeoffset = -FDT_ERR_INTERNAL;
+
+ FDT_CHECK_HEADER(fdt);
+
+ if (supernodedepth < 0)
+ return -FDT_ERR_NOTFOUND;
+
+ for (offset = 0, depth = 0;
+ (offset >= 0) && (offset <= nodeoffset);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ if (depth == supernodedepth)
+ supernodeoffset = offset;
+
+ if (offset == nodeoffset) {
+ if (nodedepth)
+ *nodedepth = depth;
+
+ if (supernodedepth > depth)
+ return -FDT_ERR_NOTFOUND;
+ else
+ return supernodeoffset;
+ }
+ }
+
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_depth(const void *fdt, int nodeoffset)
+{
+ int nodedepth;
+ int err;
+
+ err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
+ if (err)
+ return (err < 0) ? err : -FDT_ERR_INTERNAL;
+ return nodedepth;
+}
+
+int fdt_parent_offset(const void *fdt, int nodeoffset)
+{
+ int nodedepth = fdt_node_depth(fdt, nodeoffset);
+
+ if (nodedepth < 0)
+ return nodedepth;
+ return fdt_supernode_atdepth_offset(fdt, nodeoffset,
+ nodedepth - 1, NULL);
+}
+
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+ const char *propname,
+ const void *propval, int proplen)
+{
+ int offset;
+ const void *val;
+ int len;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_getprop(), then if that didn't
+ * find what we want, we scan over them again making our way
+ * to the next node. Still it's the easiest to implement
+ * approach; performance can come later. */
+ for (offset = fdt_next_node(fdt, startoffset, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ val = fdt_getprop(fdt, offset, propname, &len);
+ if (val && (len == proplen)
+ && (memcmp(val, propval, len) == 0))
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_offset_by_phandle(const void *fdt, u32 phandle)
+{
+ int offset;
+
+ if ((phandle == 0) || (phandle == -1))
+ return -FDT_ERR_BADPHANDLE;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we
+ * potentially scan each property of a node in
+ * fdt_get_phandle(), then if that didn't find what
+ * we want, we scan over them again making our way to the next
+ * node. Still it's the easiest to implement approach;
+ * performance can come later. */
+ for (offset = fdt_next_node(fdt, -1, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ if (fdt_get_phandle(fdt, offset) == phandle)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+ const char *str)
+{
+ int len = strlen(str);
+ const char *p;
+
+ while (listlen >= len) {
+ if (memcmp(str, strlist, len+1) == 0)
+ return 1;
+ p = memchr(strlist, '\0', listlen);
+ if (!p)
+ return 0; /* malformed strlist.. */
+ listlen -= (p-strlist) + 1;
+ strlist = p + 1;
+ }
+ return 0;
+}
+
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+ const char *compatible)
+{
+ const void *prop;
+ int len;
+
+ prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
+ if (!prop)
+ return len;
+ if (_fdt_stringlist_contains(prop, len, compatible))
+ return 0;
+ else
+ return 1;
+}
+
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+ const char *compatible)
+{
+ int offset, err;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_node_check_compatible(), then if
+ * that didn't find what we want, we scan over them again
+ * making our way to the next node. Still it's the easiest to
+ * implement approach; performance can come later. */
+ for (offset = fdt_next_node(fdt, startoffset, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ err = fdt_node_check_compatible(fdt, offset, compatible);
+ if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
+ return err;
+ else if (err == 0)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt_rw.c b/tests/arm64/common/basic/libfdt/fdt_rw.c
new file mode 100644
index 0000000..589084e
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_rw.c
@@ -0,0 +1,465 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_blocks_misordered(const void *fdt,
+ int mem_rsv_size, int struct_size)
+{
+ return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
+ || (fdt_off_dt_struct(fdt) <
+ (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
+ || (fdt_off_dt_strings(fdt) <
+ (fdt_off_dt_struct(fdt) + struct_size))
+ || (fdt_totalsize(fdt) <
+ (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
+}
+
+static int _fdt_rw_check_header(void *fdt)
+{
+ FDT_CHECK_HEADER(fdt);
+
+ if (fdt_version(fdt) < 17)
+ return -FDT_ERR_BADVERSION;
+ if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
+ fdt_size_dt_struct(fdt)))
+ return -FDT_ERR_BADLAYOUT;
+ if (fdt_version(fdt) > 17)
+ fdt_set_version(fdt, 17);
+
+ return 0;
+}
+
+#define FDT_RW_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = _fdt_rw_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+static inline int _fdt_data_size(void *fdt)
+{
+ return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+}
+
+static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
+{
+ char *p = splicepoint;
+ char *end = (char *)fdt + _fdt_data_size(fdt);
+
+ if (((p + oldlen) < p) || ((p + oldlen) > end))
+ return -FDT_ERR_BADOFFSET;
+ if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
+ return -FDT_ERR_NOSPACE;
+ memmove(p + newlen, p + oldlen, end - p - oldlen);
+ return 0;
+}
+
+static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
+ int oldn, int newn)
+{
+ int delta = (newn - oldn) * sizeof(*p);
+ int err;
+ err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
+ if (err)
+ return err;
+ fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
+ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+ return 0;
+}
+
+static int _fdt_splice_struct(void *fdt, void *p,
+ int oldlen, int newlen)
+{
+ int delta = newlen - oldlen;
+ int err;
+
+ if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
+ return err;
+
+ fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
+ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+ return 0;
+}
+
+static int _fdt_splice_string(void *fdt, int newlen)
+{
+ void *p = (char *)fdt
+ + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+ int err;
+
+ if ((err = _fdt_splice(fdt, p, 0, newlen)))
+ return err;
+
+ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
+ return 0;
+}
+
+static int _fdt_find_add_string(void *fdt, const char *s)
+{
+ char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
+ const char *p;
+ char *new;
+ int len = strlen(s) + 1;
+ int err;
+
+ p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
+ if (p)
+ /* found it */
+ return (p - strtab);
+
+ new = strtab + fdt_size_dt_strings(fdt);
+ err = _fdt_splice_string(fdt, len);
+ if (err)
+ return err;
+
+ memcpy(new, s, len);
+ return (new - strtab);
+}
+
+int fdt_add_mem_rsv(void *fdt, u64 address, u64 size)
+{
+ struct fdt_reserve_entry *re;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
+ err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
+ if (err)
+ return err;
+
+ re->address = cpu_to_fdt64(address);
+ re->size = cpu_to_fdt64(size);
+ return 0;
+}
+
+int fdt_del_mem_rsv(void *fdt, int n)
+{
+ struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ if (n >= fdt_num_mem_rsv(fdt))
+ return -FDT_ERR_NOTFOUND;
+
+ err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
+ if (err)
+ return err;
+ return 0;
+}
+
+static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
+ int len, struct fdt_property **prop)
+{
+ int oldlen;
+ int err;
+
+ *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+ if (! (*prop))
+ return oldlen;
+
+ if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
+ FDT_TAGALIGN(len))))
+ return err;
+
+ (*prop)->len = cpu_to_fdt32(len);
+ return 0;
+}
+
+static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
+ int len, struct fdt_property **prop)
+{
+ int proplen;
+ int nextoffset;
+ int namestroff;
+ int err;
+
+ if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ return nextoffset;
+
+ namestroff = _fdt_find_add_string(fdt, name);
+ if (namestroff < 0)
+ return namestroff;
+
+ *prop = _fdt_offset_ptr_w(fdt, nextoffset);
+ proplen = sizeof(**prop) + FDT_TAGALIGN(len);
+
+ err = _fdt_splice_struct(fdt, *prop, 0, proplen);
+ if (err)
+ return err;
+
+ (*prop)->tag = cpu_to_fdt32(FDT_PROP);
+ (*prop)->nameoff = cpu_to_fdt32(namestroff);
+ (*prop)->len = cpu_to_fdt32(len);
+ return 0;
+}
+
+int fdt_set_name(void *fdt, int nodeoffset, const char *name)
+{
+ char *namep;
+ int oldlen, newlen;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
+ if (!namep)
+ return oldlen;
+
+ newlen = strlen(name);
+
+ err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
+ FDT_TAGALIGN(newlen+1));
+ if (err)
+ return err;
+
+ memcpy(namep, name, newlen+1);
+ return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ struct fdt_property *prop;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
+ if (err == -FDT_ERR_NOTFOUND)
+ err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+ if (err)
+ return err;
+
+ memcpy(prop->data, val, len);
+ return 0;
+}
+
+int fdt_delprop(void *fdt, int nodeoffset, const char *name)
+{
+ struct fdt_property *prop;
+ int len, proplen;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+ if (! prop)
+ return len;
+
+ proplen = sizeof(*prop) + FDT_TAGALIGN(len);
+ return _fdt_splice_struct(fdt, prop, proplen, 0);
+}
+
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+ const char *name, int namelen)
+{
+ struct fdt_node_header *nh;
+ int offset, nextoffset;
+ int nodelen;
+ int err;
+ u32 tag;
+ u32 *endtag;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
+ if (offset >= 0)
+ return -FDT_ERR_EXISTS;
+ else if (offset != -FDT_ERR_NOTFOUND)
+ return offset;
+
+ /* Try to place the new node after the parent's properties */
+ fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+ } while ((tag == FDT_PROP) || (tag == FDT_NOP));
+
+ nh = _fdt_offset_ptr_w(fdt, offset);
+ nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
+
+ err = _fdt_splice_struct(fdt, nh, 0, nodelen);
+ if (err)
+ return err;
+
+ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+ memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
+ memcpy(nh->name, name, namelen);
+ endtag = (u32 *)((char *)nh + nodelen - FDT_TAGSIZE);
+ *endtag = cpu_to_fdt32(FDT_END_NODE);
+
+ return offset;
+}
+
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
+{
+ return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_del_node(void *fdt, int nodeoffset)
+{
+ int endoffset;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+ if (endoffset < 0)
+ return endoffset;
+
+ return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
+ endoffset - nodeoffset, 0);
+}
+
+static void _fdt_packblocks(const char *old, char *new,
+ int mem_rsv_size, int struct_size)
+{
+ int mem_rsv_off, struct_off, strings_off;
+
+ mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
+ struct_off = mem_rsv_off + mem_rsv_size;
+ strings_off = struct_off + struct_size;
+
+ memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
+ fdt_set_off_mem_rsvmap(new, mem_rsv_off);
+
+ memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
+ fdt_set_off_dt_struct(new, struct_off);
+ fdt_set_size_dt_struct(new, struct_size);
+
+ memmove(new + strings_off, old + fdt_off_dt_strings(old),
+ fdt_size_dt_strings(old));
+ fdt_set_off_dt_strings(new, strings_off);
+ fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
+}
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize)
+{
+ int err;
+ int mem_rsv_size, struct_size;
+ int newsize;
+ const char *fdtstart = fdt;
+ const char *fdtend = fdtstart + fdt_totalsize(fdt);
+ char *tmp;
+
+ FDT_CHECK_HEADER(fdt);
+
+ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+ * sizeof(struct fdt_reserve_entry);
+
+ if (fdt_version(fdt) >= 17) {
+ struct_size = fdt_size_dt_struct(fdt);
+ } else {
+ struct_size = 0;
+ while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
+ ;
+ if (struct_size < 0)
+ return struct_size;
+ }
+
+ if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
+ /* no further work necessary */
+ err = fdt_move(fdt, buf, bufsize);
+ if (err)
+ return err;
+ fdt_set_version(buf, 17);
+ fdt_set_size_dt_struct(buf, struct_size);
+ fdt_set_totalsize(buf, bufsize);
+ return 0;
+ }
+
+ /* Need to reorder */
+ newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
+ + struct_size + fdt_size_dt_strings(fdt);
+
+ if (bufsize < newsize)
+ return -FDT_ERR_NOSPACE;
+
+ /* First attempt to build converted tree at beginning of buffer */
+ tmp = buf;
+ /* But if that overlaps with the old tree... */
+ if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
+ /* Try right after the old tree instead */
+ tmp = (char *)(uintptr_t)fdtend;
+ if ((tmp + newsize) > ((char *)buf + bufsize))
+ return -FDT_ERR_NOSPACE;
+ }
+
+ _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
+ memmove(buf, tmp, newsize);
+
+ fdt_set_magic(buf, FDT_MAGIC);
+ fdt_set_totalsize(buf, bufsize);
+ fdt_set_version(buf, 17);
+ fdt_set_last_comp_version(buf, 16);
+ fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
+
+ return 0;
+}
+
+int fdt_pack(void *fdt)
+{
+ int mem_rsv_size;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+ * sizeof(struct fdt_reserve_entry);
+ _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+ fdt_set_totalsize(fdt, _fdt_data_size(fdt));
+
+ return 0;
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt_strerror.c b/tests/arm64/common/basic/libfdt/fdt_strerror.c
new file mode 100644
index 0000000..6aa0a46
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_strerror.c
@@ -0,0 +1,96 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+struct fdt_errtabent {
+ const char *str;
+};
+
+#define FDT_ERRTABENT(val) \
+ [(val)] = { .str = #val, }
+
+static struct fdt_errtabent fdt_errtable[] = {
+ FDT_ERRTABENT(FDT_ERR_NOTFOUND),
+ FDT_ERRTABENT(FDT_ERR_EXISTS),
+ FDT_ERRTABENT(FDT_ERR_NOSPACE),
+
+ FDT_ERRTABENT(FDT_ERR_BADOFFSET),
+ FDT_ERRTABENT(FDT_ERR_BADPATH),
+ FDT_ERRTABENT(FDT_ERR_BADSTATE),
+
+ FDT_ERRTABENT(FDT_ERR_TRUNCATED),
+ FDT_ERRTABENT(FDT_ERR_BADMAGIC),
+ FDT_ERRTABENT(FDT_ERR_BADVERSION),
+ FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
+ FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
+};
+#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
+
+const char *fdt_strerror(int errval)
+{
+ if (errval > 0)
+ return "<valid offset/length>";
+ else if (errval == 0)
+ return "<no error>";
+ else if (errval > -FDT_ERRTABSIZE) {
+ const char *s = fdt_errtable[-errval].str;
+
+ if (s)
+ return s;
+ }
+
+ return "<unknown error>";
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt_support.c b/tests/arm64/common/basic/libfdt/fdt_support.c
new file mode 100644
index 0000000..3547865
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_support.c
@@ -0,0 +1,1318 @@
+/*
+ * (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS,
vanb...@cideas.com
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#undef DEBUG
+#define debug_printf(...)
+
+#include <arm_stdio.h>
+#include <arm_string.h>
+//#include <ctype.h>
+#include <arm_types.h>
+//#include <smp.h>
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+#include <libfdt/fdt_support.h>
+
+unsigned long arm_linux_memory_size(void);
+
+#define ALIGN(x, a) (x & ~a)
+
+/**
+ * fdt_getprop_u32_default - Find a node and return it's property or a default
+ *
+ * @fdt: ptr to device tree
+ * @path: path of node
+ * @prop: property name
+ * @dflt: default value if the property isn't found
+ *
+ * Convenience function to find a node and return it's property or a
+ * default value if it doesn't exist.
+ */
+u32 fdt_getprop_u32_default(const void *fdt, const char *path,
+ const char *prop, const u32 dflt)
+{
+ const u32 *val;
+ int off;
+
+ off = fdt_path_offset(fdt, path);
+ if (off < 0)
+ return dflt;
+
+ val = fdt_getprop(fdt, off, prop, NULL);
+ if (val)
+ return fdt32_to_cpu(*val);
+ else
+ return dflt;
+}
+
+/**
+ * fdt_find_and_setprop: Find a node and set it's property
+ *
+ * @fdt: ptr to device tree
+ * @node: path of node
+ * @prop: property name
+ * @val: ptr to new value
+ * @len: length of new property value
+ * @create: flag to create the property if it doesn't exist
+ *
+ * Convenience function to directly set a property given the path to the node.
+ */
+int fdt_find_and_setprop(void *fdt, const char *node, const char *prop,
+ const void *val, int len, int create)
+{
+ int nodeoff = fdt_path_offset(fdt, node);
+
+ if (nodeoff < 0)
+ return nodeoff;
+
+ if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL))
+ return 0; /* create flag not set; so exit quietly */
+
+ return fdt_setprop(fdt, nodeoff, prop, val, len);
+}
+
+#ifdef CONFIG_OF_STDOUT_VIA_ALIAS
+
+#ifdef CONFIG_SERIAL_MULTI
+static void fdt_fill_multisername(char *sername, size_t maxlen)
+{
+ const char *outname = stdio_devices[stdout]->name;
+
+ if (strcmp(outname, "serial") > 0)
+ strncpy(sername, outname, maxlen);
+
+ /* eserial? */
+ if (strcmp(outname + 1, "serial") > 0)
+ strncpy(sername, outname + 1, maxlen);
+}
+#else
+static inline void fdt_fill_multisername(char *sername, size_t maxlen) {}
+#endif /* CONFIG_SERIAL_MULTI */
+
+static int fdt_fixup_stdout(void *fdt, int chosenoff)
+{
+ int err = 0;
+#ifdef CONFIG_CONS_INDEX
+ int node;
+ char sername[9] = { 0 };
+ const char *path;
+
+ fdt_fill_multisername(sername, sizeof(sername) - 1);
+ if (!sername[0])
+ sprintf(sername, "serial%d", CONFIG_CONS_INDEX - 1);
+
+ err = node = fdt_path_offset(fdt, "/aliases");
+ if (node >= 0) {
+ int len;
+ path = fdt_getprop(fdt, node, sername, &len);
+ if (path) {
+ char *p = malloc(len);
+ err = -FDT_ERR_NOSPACE;
+ if (p) {
+ memcpy(p, path, len);
+ err = fdt_setprop(fdt, chosenoff,
+ "linux,stdout-path", p, len);
+ free(p);
+ }
+ } else {
+ err = len;
+ }
+ }
+#endif
+ if (err < 0)
+ printf("WARNING: could not set linux,stdout-path %s.\n",
+ fdt_strerror(err));
+
+ return err;
+}
+#endif
+
+int fdt_initrd(void *fdt, unsigned long initrd_start, unsigned long initrd_end, int force)
+{
+ int nodeoffset;
+ int err, j, total;
+ u64 tmp;
+ const char *path;
+ u64 addr, size;
+
+ /* Find the "chosen" node. */
+ nodeoffset = fdt_path_offset (fdt, "/chosen");
+
+ /* If there is no "chosen" node in the blob return */
+ if (nodeoffset < 0) {
+ printf("fdt_initrd: %s\n", fdt_strerror(nodeoffset));
+ return nodeoffset;
+ }
+
+ /* just return if initrd_start/end aren't valid */
+ if ((initrd_start == 0) || (initrd_end == 0))
+ return 0;
+
+ total = fdt_num_mem_rsv(fdt);
+
+ /*
+ * Look for an existing entry and update it. If we don't find
+ * the entry, we will j be the next available slot.
+ */
+ for (j = 0; j < total; j++) {
+ err = fdt_get_mem_rsv(fdt, j, &addr, &size);
+ if (addr == initrd_start) {
+ fdt_del_mem_rsv(fdt, j);
+ break;
+ }
+ }
+
+#if 0
+ err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start);
+ if (err < 0) {
+ printf("fdt_initrd: %s\n", fdt_strerror(err));
+ return err;
+ }
+#endif
+
+ path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL);
+ if ((path == NULL) || force) {
+ tmp = cpu_to_be64(initrd_start);
+ err = fdt_setprop(fdt, nodeoffset,
+ "linux,initrd-start", &tmp, sizeof(tmp));
+ if (err < 0) {
+ printf("WARNING: "
+ "could not set linux,initrd-start %s.\n",
+ fdt_strerror(err));
+ return err;
+ }
+ tmp = cpu_to_be64(initrd_end);
+ err = fdt_setprop(fdt, nodeoffset,
+ "linux,initrd-end", &tmp, sizeof(tmp));
+ if (err < 0) {
+ printf("WARNING: could not set linux,initrd-end %s.\n",
+ fdt_strerror(err));
+
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+extern char linux_cmdline[];
+
+int fdt_chosen(void *fdt, int force)
+{
+ int nodeoffset;
+ int err;
+// char* str; /* used to set string properties */
+ const char *path;
+
+ err = fdt_check_header(fdt);
+ if (err < 0) {
+ printf("fdt_chosen: %s\n", fdt_strerror(err));
+ return err;
+ }
+
+ /*
+ * Find the "chosen" node.
+ */
+ nodeoffset = fdt_path_offset (fdt, "/chosen");
+
+ /*
+ * If there is no "chosen" node in the blob, create it.
+ */
+ if (nodeoffset < 0) {
+ /*
+ * Create a new node "/chosen" (offset 0 is root level)
+ */
+ nodeoffset = fdt_add_subnode(fdt, 0, "chosen");
+ if (nodeoffset < 0) {
+ printf("WARNING: could not create /chosen %s.\n",
+ fdt_strerror(nodeoffset));
+ return nodeoffset;
+ }
+ }
+
+ /*
+ * Create /chosen properites that don't exist in the fdt.
+ * If the property exists, update it only if the "force" parameter
+ * is true.
+ */
+// str = getenv("bootargs");
+// if (str != NULL)
+ {
+ printf("Trying to set new bootargs: %s\n", linux_cmdline);
+ path = fdt_getprop(fdt, nodeoffset, "bootargs", NULL);
+ if ((path == NULL) || force) {
+ err = fdt_setprop(fdt, nodeoffset,
+ "bootargs", linux_cmdline, strlen(linux_cmdline)+1);
+ if (err < 0)
+ printf("WARNING: could not set bootargs %s.\n",
+ fdt_strerror(err));
+ }
+ }
+
+#ifdef CONFIG_OF_STDOUT_VIA_ALIAS
+ path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL);
+ if ((path == NULL) || force)
+ err = fdt_fixup_stdout(fdt, nodeoffset);
+#endif
+
+#ifdef OF_STDOUT_PATH
+ path = fdt_getprop(fdt, nodeoffset, "linux,stdout-path", NULL);
+ if ((path == NULL) || force) {
+ err = fdt_setprop(fdt, nodeoffset,
+ "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
+ if (err < 0)
+ printf("WARNING: could not set linux,stdout-path %s.\n",
+ fdt_strerror(err));
+ }
+#endif
+
+ return err;
+}
+
+void do_fixup_by_path(void *fdt, const char *path, const char *prop,
+ const void *val, int len, int create)
+{
+#if defined(DEBUG)
+ int i;
+ debug_printf("Updating property '%s/%s' = ", path, prop);
+ for (i = 0; i < len; i++)
+ debug_printf(" %.2x", *(u8*)(val+i));
+ debug_printf("\n");
+#endif
+ int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create);
+ if (rc)
+ printf("Unable to update property %s:%s, err=%s\n",
+ path, prop, fdt_strerror(rc));
+}
+
+void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop,
+ u32 val, int create)
+{
+ val = cpu_to_fdt32(val);
+ do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create);
+}
+
+void do_fixup_by_prop(void *fdt,
+ const char *pname, const void *pval, int plen,
+ const char *prop, const void *val, int len,
+ int create)
+{
+ int off;
+#if defined(DEBUG)
+ int i;
+ debug_printf("Updating property '%s' = ", prop);
+ for (i = 0; i < len; i++)
+ debug_printf(" %.2x", *(u8*)(val+i));
+ debug_printf("\n");
+#endif
+ off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen);
+ while (off != -FDT_ERR_NOTFOUND) {
+ if (create || (fdt_get_property(fdt, off, prop, 0) != NULL))
+ fdt_setprop(fdt, off, prop, val, len);
+ off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen);
+ }
+}
+
+void do_fixup_by_prop_u32(void *fdt,
+ const char *pname, const void *pval, int plen,
+ const char *prop, u32 val, int create)
+{
+ val = cpu_to_fdt32(val);
+ do_fixup_by_prop(fdt, pname, pval, plen, prop, &val, 4, create);
+}
+
+void do_fixup_by_compat(void *fdt, const char *compat,
+ const char *prop, const void *val, int len, int create)
+{
+ int off = -1;
+#if defined(DEBUG)
+ int i;
+ debug_printf("Updating property '%s' = ", prop);
+ for (i = 0; i < len; i++)
+ debug_printf(" %.2x", *(u8*)(val+i));
+ debug_printf("\n");
+#endif
+ off = fdt_node_offset_by_compatible(fdt, -1, compat);
+ while (off != -FDT_ERR_NOTFOUND) {
+ if (create || (fdt_get_property(fdt, off, prop, 0) != NULL))
+ fdt_setprop(fdt, off, prop, val, len);
+ off = fdt_node_offset_by_compatible(fdt, off, compat);
+ }
+}
+
+void do_fixup_by_compat_u32(void *fdt, const char *compat,
+ const char *prop, u32 val, int create)
+{
+ val = cpu_to_fdt32(val);
+ do_fixup_by_compat(fdt, compat, prop, &val, 4, create);
+}
+
+/*
+ * Get cells len in bytes
+ * if #NNNN-cells property is 2 then len is 8
+ * otherwise len is 4
+ */
+static int get_cells_len(void *blob, char *nr_cells_name)
+{
+ const u32 *cell;
+
+ cell = fdt_getprop(blob, 0, nr_cells_name, NULL);
+ if (cell && fdt32_to_cpu(*cell) == 2)
+ return 8;
+
+ return 4;
+}
+
+/*
+ * Write a 4 or 8 byte big endian cell
+ */
+static void write_cell(u8 *addr, u64 val, int size)
+{
+ int shift = (size - 1) * 8;
+ while (size-- > 0) {
+ *addr++ = (val >> shift) & 0xff;
+ shift -= 8;
+ }
+}
+
+int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
+{
+ int err, nodeoffset;
+ int addr_cell_len, size_cell_len, len;
+ u8 tmp[banks * 16]; /* Up to 64-bit address + 64-bit size */
+ int bank;
+
+ err = fdt_check_header(blob);
+ if (err < 0) {
+ printf("%s: %s\n", __FUNCTION__, fdt_strerror(err));
+ return err;
+ }
+
+ /* update, or add and update /memory node */
+ nodeoffset = fdt_path_offset(blob, "/memory");
+ if (nodeoffset < 0) {
+ nodeoffset = fdt_add_subnode(blob, 0, "memory");
+ if (nodeoffset < 0)
+ printf("WARNING: could not create /memory: %s.\n",
+ fdt_strerror(nodeoffset));
+ return nodeoffset;
+ }
+ err = fdt_setprop(blob, nodeoffset, "device_type", "memory",
+ sizeof("memory"));
+ if (err < 0) {
+ printf("WARNING: could not set %s %s.\n", "device_type",
+ fdt_strerror(err));
+ return err;
+ }
+
+ addr_cell_len = get_cells_len(blob, "#address-cells");
+ size_cell_len = get_cells_len(blob, "#size-cells");
+
+ for (bank = 0, len = 0; bank < banks; bank++) {
+ write_cell(tmp + len, start[bank], addr_cell_len);
+ len += addr_cell_len;
+
+ write_cell(tmp + len, size[bank], size_cell_len);
+ len += size_cell_len;
+ }
+
+ err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
+ if (err < 0) {
+ printf("WARNING: could not set %s %s.\n",
+ "reg", fdt_strerror(err));
+ return err;
+ }
+ return 0;
+}
+
+int fdt_fixup_memory(void *blob, u64 start, u64 size)
+{
+ return fdt_fixup_memory_banks(blob, &start, &size, 1);
+}
+
+/* Resize the fdt to its actual size + a bit of padding */
+int fdt_resize(void *blob)
+{
+ int i;
+ u64 addr, size;
+ int total, ret;
+ unsigned int actualsize;
+
+ if (!blob)
+ return 0;
+
+ total = fdt_num_mem_rsv(blob);
+ for (i = 0; i < total; i++) {
+ fdt_get_mem_rsv(blob, i, &addr, &size);
+ if (addr == (unsigned long)blob) {
+ fdt_del_mem_rsv(blob, i);
+ break;
+ }
+ }
+
+ /*
+ * Calculate the actual size of the fdt
+ * plus the size needed for 5 fdt_add_mem_rsv, one
+ * for the fdt itself and 4 for a possible initrd
+ * ((initrd-start + initrd-end) * 2 (name & value))
+ */
+ actualsize = fdt_off_dt_strings(blob) +
+ fdt_size_dt_strings(blob) + 5 * sizeof(struct fdt_reserve_entry);
+
+ /* Make it so the fdt ends on a page boundary */
+ actualsize = ALIGN((actualsize + (((unsigned long)blob) & 0xfff)), 0x1000);
+ actualsize = actualsize - ((unsigned long)blob & 0xfff);
+
+ /* Change the fdt header to reflect the correct size */
+ fdt_set_totalsize(blob, actualsize);
+
+ /* Add the new reservation */
+ ret = fdt_add_mem_rsv(blob, (unsigned long)blob, actualsize);
+ if (ret < 0)
+ return ret;
+
+ return actualsize;
+}
+
+#ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE
+/*
+ * Provide a weak default function to return the flash bank size.
+ * There might be multiple non-identical flash chips connected to one
+ * chip-select, so we need to pass an index as well.
+ */
+u32 __flash_get_bank_size(int cs, int idx)
+{
+ extern flash_info_t flash_info[];
+
+ /*
+ * As default, a simple 1:1 mapping is provided. Boards with
+ * a different mapping need to supply a board specific mapping
+ * routine.
+ */
+ return flash_info[cs].size;
+}
+u32 flash_get_bank_size(int cs, int idx)
+ __attribute__((weak, alias("__flash_get_bank_size")));
+
+/*
+ * This function can be used to update the size in the "reg" property
+ * of all NOR FLASH device nodes. This is necessary for boards with
+ * non-fixed NOR FLASH sizes.
+ */
+int fdt_fixup_nor_flash_size(void *blob)
+{
+ char compat[][16] = { "cfi-flash", "jedec-flash" };
+ int off;
+ int len;
+ struct fdt_property *prop;
+ u32 *reg, *reg2;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ off = fdt_node_offset_by_compatible(blob, -1, compat[i]);
+ while (off != -FDT_ERR_NOTFOUND) {
+ int idx;
+
+ /*
+ * Found one compatible node, so fixup the size
+ * int its reg properties
+ */
+ prop = fdt_get_property_w(blob, off, "reg", &len);
+ if (prop) {
+ int tuple_size = 3 * sizeof(reg);
+
+ /*
+ * There might be multiple reg-tuples,
+ * so loop through them all
+ */
+ reg = reg2 = (u32 *)&prop->data[0];
+ for (idx = 0; idx < (len / tuple_size); idx++) {
+ /*
+ * Update size in reg property
+ */
+ reg[2] = flash_get_bank_size(reg[0],
+ idx);
+
+ /*
+ * Point to next reg tuple
+ */
+ reg += 3;
+ }
+
+ fdt_setprop(blob, off, "reg", reg2, len);
+ }
+
+ /* Move to next compatible node */
+ off = fdt_node_offset_by_compatible(blob, off,
+ compat[i]);
+ }
+ }
+
+ return 0;
+}
+#endif
+
+int fdt_increase_size(void *fdt, int add_len)
+{
+ int newlen;
+
+ newlen = fdt_totalsize(fdt) + add_len;
+
+ /* Open in place with a new len */
+ return fdt_open_into(fdt, fdt, newlen);
+}
+
+#ifdef CONFIG_FDT_FIXUP_PARTITIONS
+#include <jffs2/load_kernel.h>
+#include <mtd_node.h>
+
+struct reg_cell {
+ unsigned int r0;
+ unsigned int r1;
+};
+
+int fdt_del_subnodes(const void *blob, int parent_offset)
+{
+ int off, ndepth;
+ int ret;
+
+ for (ndepth = 0, off = fdt_next_node(blob, parent_offset, &ndepth);
+ (off >= 0) && (ndepth > 0);
+ off = fdt_next_node(blob, off, &ndepth)) {
+ if (ndepth == 1) {
+ debug_printf("delete %s: offset: %x\n",
+ fdt_get_name(blob, off, 0), off);
+ ret = fdt_del_node((void *)blob, off);
+ if (ret < 0) {
+ printf("Can't delete node: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ } else {
+ ndepth = 0;
+ off = parent_offset;
+ }
+ }
+ }
+ return 0;
+}
+
+int fdt_del_partitions(void *blob, int parent_offset)
+{
+ const void *prop;
+ int ndepth = 0;
+ int off;
+ int ret;
+
+ off = fdt_next_node(blob, parent_offset, &ndepth);
+ if (off > 0 && ndepth == 1) {
+ prop = fdt_getprop(blob, off, "label", NULL);
+ if (prop == NULL) {
+ /*
+ * Could not find label property, nand {}; node?
+ * Check subnode, delete partitions there if any.
+ */
+ return fdt_del_partitions(blob, off);
+ } else {
+ ret = fdt_del_subnodes(blob, parent_offset);
+ if (ret < 0) {
+ printf("Can't remove subnodes: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+int fdt_node_set_part_info(void *blob, int parent_offset,
+ struct mtd_device *dev)
+{
+ struct list_head *pentry;
+ struct part_info *part;
+ struct reg_cell cell;
+ int off, ndepth = 0;
+ int part_num, ret;
+ char buf[64];
+
+ ret = fdt_del_partitions(blob, parent_offset);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Check if it is nand {}; subnode, adjust
+ * the offset in this case
+ */
+ off = fdt_next_node(blob, parent_offset, &ndepth);
+ if (off > 0 && ndepth == 1)
+ parent_offset = off;
+
+ part_num = 0;
+ list_for_each_prev(pentry, &dev->parts) {
+ int newoff;
+
+ part = list_entry(pentry, struct part_info, link);
+
+ debug_printf("%2d: %-20s0x%08x\t0x%08x\t%d\n",
+ part_num, part->name, part->size,
+ part->offset, part->mask_flags);
+
+ sprintf(buf, "partition@%x", part->offset);
+add_sub:
+ ret = fdt_add_subnode(blob, parent_offset, buf);
+ if (ret == -FDT_ERR_NOSPACE) {
+ ret = fdt_increase_size(blob, 512);
+ if (!ret)
+ goto add_sub;
+ else
+ goto err_size;
+ } else if (ret < 0) {
+ printf("Can't add partition node: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ }
+ newoff = ret;
+
+ /* Check MTD_WRITEABLE_CMD flag */
+ if (part->mask_flags & 1) {
+add_ro:
+ ret = fdt_setprop(blob, newoff, "read_only", NULL, 0);
+ if (ret == -FDT_ERR_NOSPACE) {
+ ret = fdt_increase_size(blob, 512);
+ if (!ret)
+ goto add_ro;
+ else
+ goto err_size;
+ } else if (ret < 0)
+ goto err_prop;
+ }
+
+ cell.r0 = cpu_to_fdt32(part->offset);
+ cell.r1 = cpu_to_fdt32(part->size);
+add_reg:
+ ret = fdt_setprop(blob, newoff, "reg", &cell, sizeof(cell));
+ if (ret == -FDT_ERR_NOSPACE) {
+ ret = fdt_increase_size(blob, 512);
+ if (!ret)
+ goto add_reg;
+ else
+ goto err_size;
+ } else if (ret < 0)
+ goto err_prop;
+
+add_label:
+ ret = fdt_setprop_string(blob, newoff, "label", part->name);
+ if (ret == -FDT_ERR_NOSPACE) {
+ ret = fdt_increase_size(blob, 512);
+ if (!ret)
+ goto add_label;
+ else
+ goto err_size;
+ } else if (ret < 0)
+ goto err_prop;
+
+ part_num++;
+ }
+ return 0;
+err_size:
+ printf("Can't increase blob size: %s\n", fdt_strerror(ret));
+ return ret;
+err_prop:
+ printf("Can't add property: %s\n", fdt_strerror(ret));
+ return ret;
+}
+
+/*
+ * Update partitions in nor/nand nodes using info from
+ * mtdparts environment variable. The nodes to update are
+ * specified by node_info structure which contains mtd device
+ * type and compatible string: E. g. the board code in
+ * ft_board_setup() could use:
+ *
+ * struct node_info nodes[] = {
+ * { "fsl,mpc5121-nfc", MTD_DEV_TYPE_NAND, },
+ * { "cfi-flash", MTD_DEV_TYPE_NOR, },
+ * };
+ *
+ * fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
+ */
+void fdt_fixup_mtdparts(void *blob, void *node_info, int node_info_size)
+{
+ struct node_info *ni = node_info;
+ struct mtd_device *dev;
+ char *parts;
+ int i, idx;
+ int noff;
+
+ parts = getenv("mtdparts");
+ if (!parts)
+ return;
+
+ if (mtdparts_init() != 0)
+ return;
+
+ for (i = 0; i < node_info_size; i++) {
+ idx = 0;
+ noff = fdt_node_offset_by_compatible(blob, -1, ni[i].compat);
+ while (noff != -FDT_ERR_NOTFOUND) {
+ debug_printf("%s: %s, mtd dev type %d\n",
+ fdt_get_name(blob, noff, 0),
+ ni[i].compat, ni[i].type);
+ dev = device_find(ni[i].type, idx++);
+ if (dev) {
+ if (fdt_node_set_part_info(blob, noff, dev))
+ return; /* return on error */
+ }
+
+ /* Jump to next flash node */
+ noff = fdt_node_offset_by_compatible(blob, noff,
+ ni[i].compat);
+ }
+ }
+}
+#endif
+
+void fdt_del_node_and_alias(void *blob, const char *alias)
+{
+ int off = fdt_path_offset(blob, alias);
+
+ if (off < 0)
+ return;
+
+ fdt_del_node(blob, off);
+
+ off = fdt_path_offset(blob, "/aliases");
+ fdt_delprop(blob, off, alias);
+}
+
+/* Helper to read a big number; size is in cells (not bytes) */
+static inline u64 of_read_number(const u32 *cell, int size)
+{
+ u64 r = 0;
+ while (size--) {
+ r = (r << 32) | be32_to_cpu(*cell);
+ cell++;
+ }
+ return r;
+}
+
+#define PRu64 "%llx"
+
+/* Max address size we deal with */
+#define OF_MAX_ADDR_CELLS 4
+#define OF_BAD_ADDR ((u64)-1)
+#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
+ (ns) > 0)
+
+/* Debug utility */
+#ifdef DEBUG
+static void of_dump_addr(const char *s, const u32 *addr, int na)
+{
+ printf("%s", s);
+ while(na--)
+ printf(" %08x", *(addr++));
+ printf("\n");
+}
+#else
+static void of_dump_addr(const char *s, const u32 *addr, int na) { }
+#endif
+
+/* Callbacks for bus specific translators */
+struct of_bus {
+ const char *name;
+ const char *addresses;
+ void (*count_cells)(void *blob, int parentoffset,
+ int *addrc, int *sizec);
+ u64 (*map)(u32 *addr, const u32 *range,
+ int na, int ns, int pna);
+ int (*translate)(u32 *addr, u64 offset, int na);
+};
+
+/* Default translator (generic bus) */
+static void of_bus_default_count_cells(void *blob, int parentoffset,
+ int *addrc, int *sizec)
+{
+ const u32 *prop;
+
+ if (addrc) {
+ prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL);
+ if (prop)
+ *addrc = be32_to_cpup((u32 *)prop);
+ else
+ *addrc = 2;
+ }
+
+ if (sizec) {
+ prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL);
+ if (prop)
+ *sizec = be32_to_cpup((u32 *)prop);
+ else
+ *sizec = 1;
+ }
+}
+
+static u64 of_bus_default_map(u32 *addr, const u32 *range,
+ int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ cp = of_read_number(range, na);
+ s = of_read_number(range + na + pna, ns);
+ da = of_read_number(addr, na);
+
+ debug_printf("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n",
+ cp, s, da);
+
+ if (da < cp || da >= (cp + s))
+ return OF_BAD_ADDR;
+ return da - cp;
+}
+
+static int of_bus_default_translate(u32 *addr, u64 offset, int na)
+{
+ u64 a = of_read_number(addr, na);
+ memset(addr, 0, na * 4);
+ a += offset;
+ if (na > 1)
+ addr[na - 2] = a >> 32;
+ addr[na - 1] = a & 0xffffffffu;
+
+ return 0;
+}
+
+/* Array of bus specific translators */
+static struct of_bus of_busses[] = {
+ /* Default */
+ {
+ .name = "default",
+ .addresses = "reg",
+ .count_cells = of_bus_default_count_cells,
+ .map = of_bus_default_map,
+ .translate = of_bus_default_translate,
+ },
+};
+
+static int of_translate_one(void * blob, int parent, struct of_bus *bus,
+ struct of_bus *pbus, u32 *addr,
+ int na, int ns, int pna, const char *rprop)
+{
+ const u32 *ranges;
+ int rlen;
+ int rone;
+ u64 offset = OF_BAD_ADDR;
+
+ /* Normally, an absence of a "ranges" property means we are
+ * crossing a non-translatable boundary, and thus the addresses
+ * below the current not cannot be converted to CPU physical ones.
+ * Unfortunately, while this is very clear in the spec, it's not
+ * what Apple understood, and they do have things like /uni-n or
+ * /ht nodes with no "ranges" property and a lot of perfectly
+ * useable mapped devices below them. Thus we treat the absence of
+ * "ranges" as equivalent to an empty "ranges" property which means
+ * a 1:1 translation at that level. It's up to the caller not to try
+ * to translate addresses that aren't supposed to be translated in
+ * the first place. --BenH.
+ */
+ ranges = (u32 *)fdt_getprop(blob, parent, rprop, &rlen);
+ if (ranges == NULL || rlen == 0) {
+ offset = of_read_number(addr, na);
+ memset(addr, 0, pna * 4);
+ debug_printf("OF: no ranges, 1:1 translation\n");
+ goto finish;
+ }
+
+ debug_printf("OF: walking ranges...\n");
+
+ /* Now walk through the ranges */
+ rlen /= 4;
+ rone = na + pna + ns;
+ for (; rlen >= rone; rlen -= rone, ranges += rone) {
+ offset = bus->map(addr, ranges, na, ns, pna);
+ if (offset != OF_BAD_ADDR)
+ break;
+ }
+ if (offset == OF_BAD_ADDR) {
+ debug_printf("OF: not found !\n");
+ return 1;
+ }
+ memcpy(addr, ranges + na, 4 * pna);
+
+ finish:
+ of_dump_addr("OF: parent translation for:", addr, pna);
+ debug_printf("OF: with offset: "PRu64"\n", offset);
+
+ /* Translate it into parent bus space */
+ return pbus->translate(addr, offset, pna);
+}
+
+/*
+ * Translate an address from the device-tree into a CPU physical address,
+ * this walks up the tree and applies the various bus mappings on the
+ * way.
+ *
+ * Note: We consider that crossing any level with #size-cells == 0 to mean
+ * that translation is impossible (that is we are not dealing with a value
+ * that can be mapped to a cpu physical address). This is not really specified
+ * that way, but this is traditionally the way IBM at least do things
+ */
+u64 __of_translate_address(void *blob, int node_offset, const u32 *in_addr,
+ const char *rprop)
+{
+ int parent;
+ struct of_bus *bus, *pbus;
+ u32 addr[OF_MAX_ADDR_CELLS];
+ int na, ns, pna, pns;
+ u64 result = OF_BAD_ADDR;
+
+ debug_printf("OF: ** translation for device %s **\n",
+ fdt_get_name(blob, node_offset, NULL));
+
+ /* Get parent & match bus type */
+ parent = fdt_parent_offset(blob, node_offset);
+ if (parent < 0)
+ goto bail;
+ bus = &of_busses[0];
+
+ /* Cound address cells & copy address locally */
+ bus->count_cells(blob, parent, &na, &ns);
+ if (!OF_CHECK_COUNTS(na, ns)) {
+ printf("%s: Bad cell count for %s\n", __FUNCTION__,
+ fdt_get_name(blob, node_offset, NULL));
+ goto bail;
+ }
+ memcpy(addr, in_addr, na * 4);
+
+ debug_printf("OF: bus is %s (na=%d, ns=%d) on %s\n",
+ bus->name, na, ns, fdt_get_name(blob, parent, NULL));
+ of_dump_addr("OF: translating address:", addr, na);
+
+ /* Translate */
+ for (;;) {
+ /* Switch to parent bus */
+ node_offset = parent;
+ parent = fdt_parent_offset(blob, node_offset);
+
+ /* If root, we have finished */
+ if (parent < 0) {
+ debug_printf("OF: reached root node\n");
+ result = of_read_number(addr, na);
+ break;
+ }
+
+ /* Get new parent bus and counts */
+ pbus = &of_busses[0];
+ pbus->count_cells(blob, parent, &pna, &pns);
+ if (!OF_CHECK_COUNTS(pna, pns)) {
+ printf("%s: Bad cell count for %s\n", __FUNCTION__,
+ fdt_get_name(blob, node_offset, NULL));
+ break;
+ }
+
+ debug_printf("OF: parent bus is %s (na=%d, ns=%d) on %s\n",
+ pbus->name, pna, pns, fdt_get_name(blob, parent, NULL));
+
+ /* Apply bus translation */
+ if (of_translate_one(blob, node_offset, bus, pbus,
+ addr, na, ns, pna, rprop))
+ break;
+
+ /* Complete the move up one level */
+ na = pna;
+ ns = pns;
+ bus = pbus;
+
+ of_dump_addr("OF: one level translation:", addr, na);
+ }
+ bail:
+
+ return result;
+}
+
+u64 fdt_translate_address(void *blob, int node_offset, const u32 *in_addr)
+{
+ return __of_translate_address(blob, node_offset, in_addr, "ranges");
+}
+
+/**
+ * fdt_node_offset_by_compat_reg: Find a node that matches compatiable and
+ * who's reg property matches a physical cpu address
+ *
+ * @blob: ptr to device tree
+ * @compat: compatiable string to match
+ * @compat_off: property name
+ *
+ */
+int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
+ unsigned long compat_off)
+{
+ int len, off = fdt_node_offset_by_compatible(blob, -1, compat);
+ while (off != -FDT_ERR_NOTFOUND) {
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", &len);
+ if (reg) {
+ if (compat_off == fdt_translate_address(blob, off, reg))
+ return off;
+ }
+ off = fdt_node_offset_by_compatible(blob, off, compat);
+ }
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+/**
+ * fdt_alloc_phandle: Return next free phandle value
+ *
+ * @blob: ptr to device tree
+ */
+int fdt_alloc_phandle(void *blob)
+{
+ int offset, phandle = 0;
+
+ for (offset = fdt_next_node(blob, -1, NULL); offset >= 0;
+ offset = fdt_next_node(blob, offset, NULL)) {
+ phandle = max(phandle, fdt_get_phandle(blob, offset));
+ }
+
+ return phandle + 1;
+}
+
+/*
+ * fdt_set_phandle: Create a phandle property for the given node
+ *
+ * @fdt: ptr to device tree
+ * @nodeoffset: node to update
+ * @phandle: phandle value to set (must be unique)
+ */
+int fdt_set_phandle(void *fdt, int nodeoffset, u32 phandle)
+{
+ int ret;
+
+#ifdef DEBUG
+ int off = fdt_node_offset_by_phandle(fdt, phandle);
+
+ if ((off >= 0) && (off != nodeoffset)) {
+ char buf[64];
+
+ fdt_get_path(fdt, nodeoffset, buf, sizeof(buf));
+ printf("Trying to update node %s with phandle %u ",
+ buf, phandle);
+
+ fdt_get_path(fdt, off, buf, sizeof(buf));
+ printf("that already exists in node %s.\n", buf);
+ return -FDT_ERR_BADPHANDLE;
+ }
+#endif
+
+ ret = fdt_setprop_cell(fdt, nodeoffset, "phandle", phandle);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * For now, also set the deprecated "linux,phandle" property, so that we
+ * don't break older kernels.
+ */
+ ret = fdt_setprop_cell(fdt, nodeoffset, "linux,phandle", phandle);
+
+ return ret;
+}
+
+/*
+ * fdt_create_phandle: Create a phandle property for the given node
+ *
+ * @fdt: ptr to device tree
+ * @nodeoffset: node to update
+ */
+unsigned int fdt_create_phandle(void *fdt, int nodeoffset)
+{
+ /* see if there is a phandle already */
+ int phandle = fdt_get_phandle(fdt, nodeoffset);
+
+ /* if we got 0, means no phandle so create one */
+ if (phandle == 0) {
+ int ret;
+
+ phandle = fdt_alloc_phandle(fdt);
+ ret = fdt_set_phandle(fdt, nodeoffset, phandle);
+ if (ret < 0) {
+ printf("Can't set phandle %u: %s\n", phandle,
+ fdt_strerror(ret));
+ return 0;
+ }
+ }
+
+ return phandle;
+}
+
+/*
+ * fdt_set_node_status: Set status for the given node
+ *
+ * @fdt: ptr to device tree
+ * @nodeoffset: node to update
+ * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED,
+ * FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE
+ * @error_code: optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE
+ */
+int fdt_set_node_status(void *fdt, int nodeoffset,
+ enum fdt_status status, unsigned int error_code)
+{
+ char buf[16];
+ int ret = 0;
+
+ if (nodeoffset < 0)
+ return nodeoffset;
+
+ switch (status) {
+ case FDT_STATUS_OKAY:
+ ret = fdt_setprop_string(fdt, nodeoffset, "status", "okay");
+ break;
+ case FDT_STATUS_DISABLED:
+ ret = fdt_setprop_string(fdt, nodeoffset, "status", "disabled");
+ break;
+ case FDT_STATUS_FAIL:
+ ret = fdt_setprop_string(fdt, nodeoffset, "status", "fail");
+ break;
+ case FDT_STATUS_FAIL_ERROR_CODE:
+ sprintf(buf, "fail-%d", error_code);
+ ret = fdt_setprop_string(fdt, nodeoffset, "status", buf);
+ break;
+ default:
+ printf("Invalid fdt status: %x\n", status);
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * fdt_set_status_by_alias: Set status for the given node given an alias
+ *
+ * @fdt: ptr to device tree
+ * @alias: alias of node to update
+ * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED,
+ * FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE
+ * @error_code: optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE
+ */
+int fdt_set_status_by_alias(void *fdt, const char* alias,
+ enum fdt_status status, unsigned int error_code)
+{
+ int offset = fdt_path_offset(fdt, alias);
+
+ return fdt_set_node_status(fdt, offset, status, error_code);
+}
+
+#if defined(CONFIG_VIDEO)
+int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf)
+{
+ int noff;
+ int ret;
+
+ noff = fdt_node_offset_by_compatible(blob, -1, compat);
+ if (noff != -FDT_ERR_NOTFOUND) {
+ debug_printf("%s: %s\n", fdt_get_name(blob, noff, 0), compat);
+add_edid:
+ ret = fdt_setprop(blob, noff, "edid", edid_buf, 128);
+ if (ret == -FDT_ERR_NOSPACE) {
+ ret = fdt_increase_size(blob, 512);
+ if (!ret)
+ goto add_edid;
+ else
+ goto err_size;
+ } else if (ret < 0) {
+ printf("Can't add property: %s\n", fdt_strerror(ret));
+ return ret;
+ }
+ }
+ return 0;
+err_size:
+ printf("Can't increase blob size: %s\n", fdt_strerror(ret));
+ return ret;
+}
+#endif
+
+/*
+ * Verify the physical address of device tree node for a given alias
+ *
+ * This function locates the device tree node of a given alias, and then
+ * verifies that the physical address of that device matches the given
+ * parameter. It displays a message if there is a mismatch.
+ *
+ * Returns 1 on success, 0 on failure
+ */
+int fdt_verify_alias_address(void *fdt, int anode, const char *alias, u64 addr)
+{
+ const char *path;
+ const u32 *reg;
+ int node, len;
+ u64 dt_addr;
+
+ path = fdt_getprop(fdt, anode, alias, NULL);
+ if (!path) {
+ /* If there's no such alias, then it's not a failure */
+ return 1;
+ }
+
+ node = fdt_path_offset(fdt, path);
+ if (node < 0) {
+ printf("Warning: device tree alias '%s' points to invalid "
+ "node %s.\n", alias, path);
+ return 0;
+ }
+
+ reg = fdt_getprop(fdt, node, "reg", &len);
+ if (!reg) {
+ printf("Warning: device tree node '%s' has no address.\n",
+ path);
+ return 0;
+ }
+
+ dt_addr = fdt_translate_address(fdt, node, reg);
+ if (addr != dt_addr) {
+ printf("Warning: U-Boot configured device %s at address %llx,\n"
+ " but the device tree has it address %llx.\n",
+ alias, addr, dt_addr);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Returns the base address of an SOC or PCI node
+ */
+u64 fdt_get_base_address(void *fdt, int node)
+{
+ int size;
+ u32 naddr;
+ const u32 *prop;
+
+ prop = fdt_getprop(fdt, node, "#address-cells", &size);
+ if (prop && size == 4)
+ naddr = *prop;
+ else
+ naddr = 2;
+
+ prop = fdt_getprop(fdt, node, "ranges", &size);
+
+ return prop ? fdt_translate_address(fdt, node, prop + naddr) : 0;
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt_support.h b/tests/arm64/common/basic/libfdt/fdt_support.h
new file mode 100644
index 0000000..d32ec6c
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_support.h
@@ -0,0 +1,123 @@
+/*
+ * (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS,
vanb...@cideas.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FDT_SUPPORT_H
+#define __FDT_SUPPORT_H
+
+#include <arm_string.h>
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt_env.h>
+
+static void inline strtoul(char *s, void *ptr, int ign, unsigned long *value)
+{
+ *value = arm_hexstr2ulonglong(s);
+}
+
+u32 fdt_getprop_u32_default(const void *fdt, const char *path,
+ const char *prop, const u32 dflt);
+int fdt_chosen(void *fdt, int force);
+int fdt_initrd(void *fdt, unsigned long initrd_start, unsigned long initrd_end, int force);
+void do_fixup_by_path(void *fdt, const char *path, const char *prop,
+ const void *val, int len, int create);
+void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop,
+ u32 val, int create);
+
+static inline void do_fixup_by_path_string(void *fdt, const char *path,
+ const char *prop, const char *status)
+{
+ do_fixup_by_path(fdt, path, prop, status, strlen(status) + 1, 1);
+}
+
+void do_fixup_by_prop(void *fdt,
+ const char *pname, const void *pval, int plen,
+ const char *prop, const void *val, int len,
+ int create);
+void do_fixup_by_prop_u32(void *fdt,
+ const char *pname, const void *pval, int plen,
+ const char *prop, u32 val, int create);
+void do_fixup_by_compat(void *fdt, const char *compat,
+ const char *prop, const void *val, int len, int create);
+void do_fixup_by_compat_u32(void *fdt, const char *compat,
+ const char *prop, u32 val, int create);
+int fdt_fixup_memory(void *blob, u64 start, u64 size);
+int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks);
+void fdt_fixup_ethernet(void *fdt);
+int fdt_find_and_setprop(void *fdt, const char *node, const char *prop,
+ const void *val, int len, int create);
+void fdt_fixup_qe_firmware(void *fdt);
+
+#ifdef CONFIG_OF_BOARD_SETUP
+void ft_board_setup(void *blob, bd_t *bd);
+void ft_cpu_setup(void *blob, bd_t *bd);
+void ft_pci_setup(void *blob, bd_t *bd);
+#endif
+
+void set_working_fdt_addr(void *addr);
+int fdt_resize(void *blob);
+int fdt_increase_size(void *fdt, int add_len);
+
+int fdt_fixup_nor_flash_size(void *blob);
+
+void fdt_fixup_mtdparts(void *fdt, void *node_info, int node_info_size);
+void fdt_del_node_and_alias(void *blob, const char *alias);
+u64 fdt_translate_address(void *blob, int node_offset, const u32 *in_addr);
+int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
+ unsigned long compat_off);
+int fdt_alloc_phandle(void *blob);
+int fdt_set_phandle(void *fdt, int nodeoffset, u32 phandle);
+unsigned int fdt_create_phandle(void *fdt, int nodeoffset);
+int fdt_add_edid(void *blob, const char *compat, unsigned char *buf);
+
+int fdt_verify_alias_address(void *fdt, int anode, const char *alias,
+ u64 addr);
+u64 fdt_get_base_address(void *fdt, int node);
+
+enum fdt_status {
+ FDT_STATUS_OKAY,
+ FDT_STATUS_DISABLED,
+ FDT_STATUS_FAIL,
+ FDT_STATUS_FAIL_ERROR_CODE,
+};
+int fdt_set_node_status(void *fdt, int nodeoffset,
+ enum fdt_status status, unsigned int error_code);
+static inline int fdt_status_okay(void *fdt, int nodeoffset)
+{
+ return fdt_set_node_status(fdt, nodeoffset, FDT_STATUS_OKAY, 0);
+}
+static inline int fdt_status_disabled(void *fdt, int nodeoffset)
+{
+ return fdt_set_node_status(fdt, nodeoffset, FDT_STATUS_DISABLED, 0);
+}
+
+int fdt_set_status_by_alias(void *fdt, const char* alias,
+ enum fdt_status status, unsigned int error_code);
+static inline int fdt_status_okay_by_alias(void *fdt, const char* alias)
+{
+ return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_OKAY, 0);
+}
+static inline int fdt_status_disabled_by_alias(void *fdt, const char* alias)
+{
+ return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_DISABLED, 0);
+}
+
+#endif /* ifndef __FDT_SUPPORT_H */
diff --git a/tests/arm64/common/basic/libfdt/fdt_sw.c b/tests/arm64/common/basic/libfdt/fdt_sw.c
new file mode 100644
index 0000000..69bc572
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_sw.c
@@ -0,0 +1,256 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_sw_check_header(void *fdt)
+{
+ if (fdt_magic(fdt) != FDT_SW_MAGIC)
+ return -FDT_ERR_BADMAGIC;
+ /* FIXME: should check more details about the header state */
+ return 0;
+}
+
+#define FDT_SW_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = _fdt_sw_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+static void *_fdt_grab_space(void *fdt, size_t len)
+{
+ int offset = fdt_size_dt_struct(fdt);
+ int spaceleft;
+
+ spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
+ - fdt_size_dt_strings(fdt);
+
+ if ((offset + len < offset) || (offset + len > spaceleft))
+ return NULL;
+
+ fdt_set_size_dt_struct(fdt, offset + len);
+ return _fdt_offset_ptr_w(fdt, offset);
+}
+
+int fdt_create(void *buf, int bufsize)
+{
+ void *fdt = buf;
+
+ if (bufsize < sizeof(struct fdt_header))
+ return -FDT_ERR_NOSPACE;
+
+ memset(buf, 0, bufsize);
+
+ fdt_set_magic(fdt, FDT_SW_MAGIC);
+ fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_totalsize(fdt, bufsize);
+
+ fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
+ sizeof(struct fdt_reserve_entry)));
+ fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
+ fdt_set_off_dt_strings(fdt, bufsize);
+
+ return 0;
+}
+
+int fdt_add_reservemap_entry(void *fdt, u64 addr, u64 size)
+{
+ struct fdt_reserve_entry *re;
+ int offset;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ if (fdt_size_dt_struct(fdt))
+ return -FDT_ERR_BADSTATE;
+
+ offset = fdt_off_dt_struct(fdt);
+ if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
+ return -FDT_ERR_NOSPACE;
+
+ re = (struct fdt_reserve_entry *)((char *)fdt + offset);
+ re->address = cpu_to_fdt64(addr);
+ re->size = cpu_to_fdt64(size);
+
+ fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
+
+ return 0;
+}
+
+int fdt_finish_reservemap(void *fdt)
+{
+ return fdt_add_reservemap_entry(fdt, 0, 0);
+}
+
+int fdt_begin_node(void *fdt, const char *name)
+{
+ struct fdt_node_header *nh;
+ int namelen = strlen(name) + 1;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
+ if (! nh)
+ return -FDT_ERR_NOSPACE;
+
+ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+ memcpy(nh->name, name, namelen);
+ return 0;
+}
+
+int fdt_end_node(void *fdt)
+{
+ u32 *en;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ en = _fdt_grab_space(fdt, FDT_TAGSIZE);
+ if (! en)
+ return -FDT_ERR_NOSPACE;
+
+ *en = cpu_to_fdt32(FDT_END_NODE);
+ return 0;
+}
+
+static int _fdt_find_add_string(void *fdt, const char *s)
+{
+ char *strtab = (char *)fdt + fdt_totalsize(fdt);
+ const char *p;
+ int strtabsize = fdt_size_dt_strings(fdt);
+ int len = strlen(s) + 1;
+ int struct_top, offset;
+
+ p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
+ if (p)
+ return p - strtab;
+
+ /* Add it */
+ offset = -strtabsize - len;
+ struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+ if (fdt_totalsize(fdt) + offset < struct_top)
+ return 0; /* no more room :( */
+
+ memcpy(strtab + offset, s, len);
+ fdt_set_size_dt_strings(fdt, strtabsize + len);
+ return offset;
+}
+
+int fdt_property(void *fdt, const char *name, const void *val, int len)
+{
+ struct fdt_property *prop;
+ int nameoff;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ nameoff = _fdt_find_add_string(fdt, name);
+ if (nameoff == 0)
+ return -FDT_ERR_NOSPACE;
+
+ prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
+ if (! prop)
+ return -FDT_ERR_NOSPACE;
+
+ prop->tag = cpu_to_fdt32(FDT_PROP);
+ prop->nameoff = cpu_to_fdt32(nameoff);
+ prop->len = cpu_to_fdt32(len);
+ memcpy(prop->data, val, len);
+ return 0;
+}
+
+int fdt_finish(void *fdt)
+{
+ char *p = (char *)fdt;
+ u32 *end;
+ int oldstroffset, newstroffset;
+ u32 tag;
+ int offset, nextoffset;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ /* Add terminator */
+ end = _fdt_grab_space(fdt, sizeof(*end));
+ if (! end)
+ return -FDT_ERR_NOSPACE;
+ *end = cpu_to_fdt32(FDT_END);
+
+ /* Relocate the string table */
+ oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
+ newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+ memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
+ fdt_set_off_dt_strings(fdt, newstroffset);
+
+ /* Walk the structure, correcting string offsets */
+ offset = 0;
+ while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
+ if (tag == FDT_PROP) {
+ struct fdt_property *prop =
+ _fdt_offset_ptr_w(fdt, offset);
+ int nameoff;
+
+ nameoff = fdt32_to_cpu(prop->nameoff);
+ nameoff += fdt_size_dt_strings(fdt);
+ prop->nameoff = cpu_to_fdt32(nameoff);
+ }
+ offset = nextoffset;
+ }
+ if (nextoffset < 0)
+ return nextoffset;
+
+ /* Finally, adjust the header */
+ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+ fdt_set_magic(fdt, FDT_MAGIC);
+ return 0;
+}
diff --git a/tests/arm64/common/basic/libfdt/fdt_wip.c b/tests/arm64/common/basic/libfdt/fdt_wip.c
new file mode 100644
index 0000000..d0e4bc9
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/fdt_wip.c
@@ -0,0 +1,118 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/libfdt_env.h>
+
+#include <libfdt/fdt.h>
+#include <libfdt/libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ void *propval;
+ int proplen;
+
+ propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+ if (! propval)
+ return proplen;
+
+ if (proplen != len)
+ return -FDT_ERR_NOSPACE;
+
+ memcpy(propval, val, len);
+ return 0;
+}
+
+static void _fdt_nop_region(void *start, int len)
+{
+ u32 *p;
+
+ for (p = start; (char *)p < ((char *)start + len); p++)
+ *p = cpu_to_fdt32(FDT_NOP);
+}
+
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
+{
+ struct fdt_property *prop;
+ int len;
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+ if (! prop)
+ return len;
+
+ _fdt_nop_region(prop, len + sizeof(*prop));
+
+ return 0;
+}
+
+int _fdt_node_end_offset(void *fdt, int offset)
+{
+ int depth = 0;
+
+ while ((offset >= 0) && (depth >= 0))
+ offset = fdt_next_node(fdt, offset, &depth);
+
+ return offset;
+}
+
+int fdt_nop_node(void *fdt, int nodeoffset)
+{
+ int endoffset;
+
+ endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+ if (endoffset < 0)
+ return endoffset;
+
+ _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
+ endoffset - nodeoffset);
+ return 0;
+}
diff --git a/tests/arm64/common/basic/libfdt/libfdt.h b/tests/arm64/common/basic/libfdt/libfdt.h
new file mode 100644
index 0000000..f74b3e3
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/libfdt.h
@@ -0,0 +1,1237 @@
+#ifndef _LIBFDT_H
+#define _LIBFDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libfdt/libfdt_env.h>
+#include <libfdt/fdt.h>
+
+typedef unsigned long int uintptr_t;
+
+#define FDT_FIRST_SUPPORTED_VERSION 0x10
+#define FDT_LAST_SUPPORTED_VERSION 0x11
+
+/* Error codes: informative error codes */
+#define FDT_ERR_NOTFOUND 1
+ /* FDT_ERR_NOTFOUND: The requested node or property does not exist */
+#define FDT_ERR_EXISTS 2
+ /* FDT_ERR_EXISTS: Attemped to create a node or property which
+ * already exists */
+#define FDT_ERR_NOSPACE 3
+ /* FDT_ERR_NOSPACE: Operation needed to expand the device
+ * tree, but its buffer did not have sufficient space to
+ * contain the expanded tree. Use fdt_open_into() to move the
+ * device tree to a buffer with more space. */
+
+/* Error codes: codes for bad parameters */
+#define FDT_ERR_BADOFFSET 4
+ /* FDT_ERR_BADOFFSET: Function was passed a structure block
+ * offset which is out-of-bounds, or which points to an
+ * unsuitable part of the structure for the operation. */
+#define FDT_ERR_BADPATH 5
+ /* FDT_ERR_BADPATH: Function was passed a badly formatted path
+ * (e.g. missing a leading / for a function which requires an
+ * absolute path) */
+#define FDT_ERR_BADPHANDLE 6
+ /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
+ * value. phandle values of 0 and -1 are not permitted. */
+#define FDT_ERR_BADSTATE 7
+ /* FDT_ERR_BADSTATE: Function was passed an incomplete device
+ * tree created by the sequential-write functions, which is
+ * not sufficiently complete for the requested operation. */
+
+/* Error codes: codes for bad device tree blobs */
+#define FDT_ERR_TRUNCATED 8
+ /* FDT_ERR_TRUNCATED: Structure block of the given device tree
+ * ends without an FDT_END tag. */
+#define FDT_ERR_BADMAGIC 9
+ /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
+ * device tree at all - it is missing the flattened device
+ * tree magic number. */
+#define FDT_ERR_BADVERSION 10
+ /* FDT_ERR_BADVERSION: Given device tree has a version which
+ * can't be handled by the requested operation. For
+ * read-write functions, this may mean that fdt_open_into() is
+ * required to convert the tree to the expected version. */
+#define FDT_ERR_BADSTRUCTURE 11
+ /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
+ * structure block or other serious error (e.g. misnested
+ * nodes, or subnodes preceding properties). */
+#define FDT_ERR_BADLAYOUT 12
+ /* FDT_ERR_BADLAYOUT: For read-write functions, the given
+ * device tree has it's sub-blocks in an order that the
+ * function can't handle (memory reserve map, then structure,
+ * then strings). Use fdt_open_into() to reorganize the tree
+ * into a form suitable for the read-write operations. */
+
+/* "Can't happen" error indicating a bug in libfdt */
+#define FDT_ERR_INTERNAL 13
+ /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
+ * Should never be returned, if it is, it indicates a bug in
+ * libfdt itself. */
+
+#define FDT_ERR_MAX 13
+
+/**********************************************************************/
+/* Low-level functions (you probably don't need these) */
+/**********************************************************************/
+
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
+static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
+{
+ return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
+}
+
+u32 fdt_next_tag(const void *fdt, int offset, int *nextoffset);
+
+/**********************************************************************/
+/* Traversal functions */
+/**********************************************************************/
+
+int fdt_next_node(const void *fdt, int offset, int *depth);
+
+/**********************************************************************/
+/* General functions */
+/**********************************************************************/
+
+#define fdt_get_header(fdt, field) \
+ (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
+#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
+#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
+#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
+#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
+#define fdt_version(fdt) (fdt_get_header(fdt, version))
+#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
+#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
+#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
+#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
+
+#define __fdt_set_hdr(name) \
+ static inline void fdt_set_##name(void *fdt, u32 val) \
+ { \
+ struct fdt_header *fdth = (struct fdt_header*)fdt; \
+ fdth->name = cpu_to_fdt32(val); \
+ }
+__fdt_set_hdr(magic);
+__fdt_set_hdr(totalsize);
+__fdt_set_hdr(off_dt_struct);
+__fdt_set_hdr(off_dt_strings);
+__fdt_set_hdr(off_mem_rsvmap);
+__fdt_set_hdr(version);
+__fdt_set_hdr(last_comp_version);
+__fdt_set_hdr(boot_cpuid_phys);
+__fdt_set_hdr(size_dt_strings);
+__fdt_set_hdr(size_dt_struct);
+#undef __fdt_set_hdr
+
+/**
+ * fdt_check_header - sanity check a device tree or possible device tree
+ * @fdt: pointer to data which might be a flattened device tree
+ *
+ * fdt_check_header() checks that the given buffer contains what
+ * appears to be a flattened device tree with sane information in its
+ * header.
+ *
+ * returns:
+ * 0, if the buffer appears to contain a valid device tree
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings, as above
+ */
+int fdt_check_header(const void *fdt);
+
+/**
+ * fdt_move - move a device tree around in memory
+ * @fdt: pointer to the device tree to move
+ * @buf: pointer to memory where the device is to be moved
+ * @bufsize: size of the memory space at buf
+ *
+ * fdt_move() relocates, if possible, the device tree blob located at
+ * fdt to the buffer at buf of size bufsize. The buffer may overlap
+ * with the existing device tree blob at fdt. Therefore,
+ * fdt_move(fdt, fdt, fdt_totalsize(fdt))
+ * should always succeed.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_move(const void *fdt, void *buf, int bufsize);
+
+/**********************************************************************/
+/* Read-only functions */
+/**********************************************************************/
+
+/**
+ * fdt_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ *
+ * fdt_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt.
+ *
+ * returns:
+ * a pointer to the string, on success
+ * NULL, if stroffset is out of bounds
+ */
+const char *fdt_string(const void *fdt, int stroffset);
+
+/**
+ * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
+ * @fdt: pointer to the device tree blob
+ *
+ * Returns the number of entries in the device tree blob's memory
+ * reservation map. This does not include the terminating 0,0 entry
+ * or any other (0,0) entries reserved for expansion.
+ *
+ * returns:
+ * the number of entries
+ */
+int fdt_num_mem_rsv(const void *fdt);
+
+/**
+ * fdt_get_mem_rsv - retrieve one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: pointers to 64-bit variables
+ *
+ * On success, *address and *size will contain the address and size of
+ * the n-th reserve map entry from the device tree blob, in
+ * native-endian format.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_get_mem_rsv(const void *fdt, int n, u64 *address, u64 *size);
+
+/**
+ * fdt_subnode_offset_namelen - find a subnode based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_subnode_offset(), but only examine the first
+ * namelen characters of name for matching the subnode name. This is
+ * useful for finding subnodes based on a portion of a larger string,
+ * such as a full path.
+ */
+int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+ const char *name, int namelen);
+/**
+ * fdt_subnode_offset - find a subnode of a given node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_subnode_offset() finds a subnode of the node at structure block
+ * offset parentoffset with the given name. name may include a unit
+ * address, in which case fdt_subnode_offset() will find the subnode
+ * with that unit address, or the unit address may be omitted, in
+ * which case fdt_subnode_offset() will find an arbitrary subnode
+ * whose name excluding unit address matches the given name.
+ *
+ * returns:
+ * structure block offset of the requested subnode (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_path_offset - find a tree node by its full path
+ * @fdt: pointer to the device tree blob
+ * @path: full path of the node to locate
+ *
+ * fdt_path_offset() finds a node of a given path in the device tree.
+ * Each path component may omit the unit address portion, but the
+ * results of this are undefined if any such path component is
+ * ambiguous (that is if there are multiple nodes at the relevant
+ * level matching the given component, differentiated only by unit
+ * address).
+ *
+ * returns:
+ * structure block offset of the node with the requested path (>=0), on success
+ * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
+ * -FDT_ERR_NOTFOUND, if the requested node does not exist
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_path_offset(const void *fdt, const char *path);
+
+/**
+ * fdt_get_name - retrieve the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the starting node
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_name() retrieves the name (including unit address) of the
+ * device tree node at structure block offset nodeoffset. If lenp is
+ * non-NULL, the length of this name is also returned, in the integer
+ * pointed to by lenp.
+ *
+ * returns:
+ * pointer to the node's name, on success
+ * If lenp is non-NULL, *lenp contains the length of that name (>=0)
+ * NULL, on error
+ * if lenp is non-NULL *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
+
+/**
+ * fdt_first_property_offset - find the offset of a node's first property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ *
+ * fdt_first_property_offset() finds the first property of the node at
+ * the given structure block offset.
+ *
+ * returns:
+ * structure block offset of the property (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested node has no properties
+ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_first_property_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_next_property_offset - step through a node's properties
+ * @fdt: pointer to the device tree blob
+ * @offset: structure block offset of a property
+ *
+ * fdt_next_property_offset() finds the property immediately after the
+ * one at the given structure block offset. This will be a property
+ * of the same node as the given property.
+ *
+ * returns:
+ * structure block offset of the next property (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the given property is the last in its node
+ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_next_property_offset(const void *fdt, int offset);
+
+/**
+ * fdt_get_property_by_offset - retrieve the property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @offset: offset of the property to retrieve
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property_by_offset() retrieves a pointer to the
+ * fdt_property structure within the device tree blob at the given
+ * offset. If lenp is non-NULL, the length of the property value is
+ * also returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the structure representing the property
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp);
+
+/**
+ * fdt_get_property_namelen - find a property based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_get_property_namelen(), but only examine the first
+ * namelen characters of name for matching the property name.
+ */
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int nodeoffset,
+ const char *name,
+ int namelen, int *lenp);
+
+/**
+ * fdt_get_property - find a given property in a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property() retrieves a pointer to the fdt_property
+ * structure within the device tree blob corresponding to the property
+ * named 'name' of the node at offset nodeoffset. If lenp is
+ * non-NULL, the length of the property value is also returned, in the
+ * integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the structure representing the property
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_NOTFOUND, node does not have named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
+ const char *name, int *lenp);
+static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
+ const char *name,
+ int *lenp)
+{
+ return (struct fdt_property *)(uintptr_t)
+ fdt_get_property(fdt, nodeoffset, name, lenp);
+}
+
+/**
+ * fdt_getprop_by_offset - retrieve the value of a property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @ffset: offset of the property to read
+ * @namep: pointer to a string variable (will be overwritten) or NULL
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop_by_offset() retrieves a pointer to the value of the
+ * property at structure block offset 'offset' (this will be a pointer
+ * to within the device blob itself, not a copy of the value). If
+ * lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp. If namep is non-NULL,
+ * the property's namne will also be returned in the char * pointed to
+ * by namep (this will be a pointer to within the device tree's string
+ * block, not a new copy of the name).
+ *
+ * returns:
+ * pointer to the property's value
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * if namep is non-NULL *namep contiains a pointer to the property
+ * name.
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+ const char **namep, int *lenp);
+
+/**
+ * fdt_getprop_namelen - get property value based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_getprop(), but only examine the first namelen
+ * characters of name for matching the property name.
+ */
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp);
+
+/**
+ * fdt_getprop - retrieve the value of a given property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop() retrieves a pointer to the value of the property
+ * named 'name' of the node at offset nodeoffset (this will be a
+ * pointer to within the device blob itself, not a copy of the value).
+ * If lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the property's value
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_NOTFOUND, node does not have named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp);
+static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
+}
+
+/**
+ * fdt_get_phandle - retrieve the phandle of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the node
+ *
+ * fdt_get_phandle() retrieves the phandle of the device tree node at
+ * structure block offset nodeoffset.
+ *
+ * returns:
+ * the phandle of the node at nodeoffset, on success (!= 0, != -1)
+ * 0, if the node has no phandle, or another error occurs
+ */
+u32 fdt_get_phandle(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_get_alias_namelen - get alias based on substring
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_get_alias(), but only examine the first namelen
+ * characters of name for matching the alias name.
+ */
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen);
+
+/**
+ * fdt_get_alias - retreive the path referenced by a given alias
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ *
+ * fdt_get_alias() retrieves the value of a given alias. That is, the
+ * value of the property named 'name' in the node /aliases.
+ *
+ * returns:
+ * a pointer to the expansion of the alias named 'name', of it exists
+ * NULL, if the given alias or the /aliases node does not exist
+ */
+const char *fdt_get_alias(const void *fdt, const char *name);
+
+/**
+ * fdt_get_path - determine the full path of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose path to find
+ * @buf: character buffer to contain the returned path (will be overwritten)
+ * @buflen: size of the character buffer at buf
+ *
+ * fdt_get_path() computes the full path of the node at offset
+ * nodeoffset, and records that path in the buffer at buf.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ * 0, on success
+ * buf contains the absolute path of the node at
+ * nodeoffset, as a NUL-terminated string.
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
+ * characters and will not fit in the given buffer.
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
+
+/**
+ * fdt_supernode_atdepth_offset - find a specific ancestor of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ * @supernodedepth: depth of the ancestor to find
+ * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_supernode_atdepth_offset() finds an ancestor of the given node
+ * at a specific depth from the root (where the root itself has depth
+ * 0, its immediate subnodes depth 1 and so forth). So
+ * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
+ * will always return 0, the offset of the root node. If the node at
+ * nodeoffset has depth D, then:
+ * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
+ * will return nodeoffset itself.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+
+ * structure block offset of the node at node offset's ancestor
+ * of depth supernodedepth (>=0), on success
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+ int supernodedepth, int *nodedepth);
+
+/**
+ * fdt_node_depth - find the depth of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_node_depth() finds the depth of a given node. The root node
+ * has depth 0, its immediate subnodes depth 1 and so forth.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ * depth of the node at nodeoffset (>=0), on success
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_depth(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_parent_offset - find the parent of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_parent_offset() locates the parent node of a given node (that
+ * is, it finds the offset of the node which contains the node at
+ * nodeoffset as a subnode).
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset, *twice*.
+ *
+ * returns:
+ * structure block offset of the parent of the node at nodeoffset
+ * (>=0), on success
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_parent_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_node_offset_by_prop_value - find nodes with a given property value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @propname: property name to check
+ * @propval: property value to search for
+ * @proplen: length of the value in propval
+ *
+ * fdt_node_offset_by_prop_value() returns the offset of the first
+ * node after startoffset, which has a property named propname whose
+ * value is of length proplen and has value equal to propval; or if
+ * startoffset is -1, the very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ * offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
+ * propval, proplen);
+ * while (offset != -FDT_ERR_NOTFOUND) {
+ * ... other code here ...
+ * offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
+ * propval, proplen);
+ * }
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0, >startoffset),
+ * on success
+ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ * tree after startoffset
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+ const char *propname,
+ const void *propval, int proplen);
+
+/**
+ * fdt_node_offset_by_phandle - find the node with a given phandle
+ * @fdt: pointer to the device tree blob
+ * @phandle: phandle value
+ *
+ * fdt_node_offset_by_phandle() returns the offset of the node
+ * which has the given phandle value. If there is more than one node
+ * in the tree with the given phandle (an invalid tree), results are
+ * undefined.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0), on success
+ * -FDT_ERR_NOTFOUND, no node with that phandle exists
+ * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_phandle(const void *fdt, u32 phandle);
+
+/**
+ * fdt_node_check_compatible: check a node's compatible property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @compatible: string to match against
+ *
+ *
+ * fdt_node_check_compatible() returns 0 if the given node contains a
+ * 'compatible' property with the given string as one of its elements,
+ * it returns non-zero otherwise, or on error.
+ *
+ * returns:
+ * 0, if the node has a 'compatible' property listing the given string
+ * 1, if the node has a 'compatible' property, but it does not list
+ * the given string
+ * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
+ * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+ const char *compatible);
+
+/**
+ * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @compatible: 'compatible' string to match against
+ *
+ * fdt_node_offset_by_compatible() returns the offset of the first
+ * node after startoffset, which has a 'compatible' property which
+ * lists the given compatible string; or if startoffset is -1, the
+ * very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ * offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
+ * while (offset != -FDT_ERR_NOTFOUND) {
+ * ... other code here ...
+ * offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
+ * }
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0, >startoffset),
+ * on success
+ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ * tree after startoffset
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+ const char *compatible);
+
+/**********************************************************************/
+/* Write-in-place functions */
+/**********************************************************************/
+
+/**
+ * fdt_setprop_inplace - change a property's value, but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * fdt_setprop_inplace() replaces the value of a given property with
+ * the data in val, of length len. This function cannot change the
+ * size of a property, and so will only work if len is equal to the
+ * current length of the property.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, if len is not equal to the property's current length
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len);
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: cell (32-bit integer) value to replace the property with
+ *
+ * fdt_setprop_inplace_cell() replaces the value of a given property
+ * with the 32-bit integer cell value in val, converting val to
+ * big-endian if necessary. This function cannot change the size of a
+ * property, and so will only work if the property already exists and
+ * has length 4.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, if the property's length is not equal to 4
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+ const char *name, u32 val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_nop_property - replace a property with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_nop_property() will replace a given property's representation
+ * in the blob with FDT_NOP tags, effectively removing it from the
+ * tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the property, and will not alter or move any other part of the
+ * tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_nop_node - replace a node (subtree) with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_nop_node() will replace a given node's representation in the
+ * blob, including all its subnodes, if any, with FDT_NOP tags,
+ * effectively removing it from the tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the node and its properties and subnodes, and will not alter or
+ * move any other part of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_nop_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Sequential write functions */
+/**********************************************************************/
+
+int fdt_create(void *buf, int bufsize);
+int fdt_add_reservemap_entry(void *fdt, u64 addr, u64 size);
+int fdt_finish_reservemap(void *fdt);
+int fdt_begin_node(void *fdt, const char *name);
+int fdt_property(void *fdt, const char *name, const void *val, int len);
+static inline int fdt_property_cell(void *fdt, const char *name, u32 val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_property(fdt, name, &val, sizeof(val));
+}
+#define fdt_property_string(fdt, name, str) \
+ fdt_property(fdt, name, str, strlen(str)+1)
+int fdt_end_node(void *fdt);
+int fdt_finish(void *fdt);
+
+/**********************************************************************/
+/* Read-write functions */
+/**********************************************************************/
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize);
+int fdt_pack(void *fdt);
+
+/**
+ * fdt_add_mem_rsv - add one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: 64-bit values (native endian)
+ *
+ * Adds a reserve map entry to the given blob reserving a region at
+ * address address of length size.
+ *
+ * This function will insert data into the reserve map and will
+ * therefore change the indexes of some entries in the table.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new reservation entry
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_add_mem_rsv(void *fdt, u64 address, u64 size);
+
+/**
+ * fdt_del_mem_rsv - remove a memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @n: entry to remove
+ *
+ * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
+ * the blob.
+ *
+ * This function will delete data from the reservation table and will
+ * therefore change the indexes of some entries in the table.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
+ * are less than n+1 reserve map entries)
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_del_mem_rsv(void *fdt, int n);
+
+/**
+ * fdt_set_name - change the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ * @name: name to give the node
+ *
+ * fdt_set_name() replaces the name (including unit address, if any)
+ * of the given node with the given string. NOTE: this function can't
+ * efficiently check if the new name is unique amongst the given
+ * node's siblings; results are undefined if this function is invoked
+ * with a name equal to one of the given node's siblings.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob
+ * to contain the new name
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_set_name(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_setprop - create or change a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to set the property value to
+ * @len: length of the property value
+ *
+ * fdt_setprop() sets the value of the named property in the given
+ * node to the given value and length, creating the property if it
+ * does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len);
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_cell() sets the value of the named property in the
+ * given node to the given cell value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+ u32 val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_string - set a property to a string value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value for the property
+ *
+ * fdt_setprop_string() sets the value of the named property in the
+ * given node to the given string value (using the length of the
+ * string to determine the new length of the property), or creates a
+ * new property with that value if it does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_setprop_string(fdt, nodeoffset, name, str) \
+ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
+ * fdt_delprop - delete a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_del_property() will delete the given property.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_delprop(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_add_subnode_namelen - creates a new node based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_add_subnode(), but use only the first namelen
+ * characters of name as the name of the new node. This is useful for
+ * creating subnodes based on a portion of a larger string, such as a
+ * full path.
+ */
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+ const char *name, int namelen);
+
+/**
+ * fdt_add_subnode - creates a new node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_add_subnode() creates a new node as a subnode of the node at
+ * structure block offset parentoffset, with the given name (which
+ * should include the unit address, if any).
+ *
+ * This function will insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+
+ * returns:
+ * structure block offset of the created nodeequested subnode (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
+ * the given name
+ * -FDT_ERR_NOSPACE, if there is insufficient free space in the
+ * blob to contain the new node
+ * -FDT_ERR_NOSPACE
+ * -FDT_ERR_BADLAYOUT
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_del_node - delete a node (subtree)
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_del_node() will remove the given node, including all its
+ * subnodes if any, from the blob.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_del_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Debugging / informational functions */
+/**********************************************************************/
+
+const char *fdt_strerror(int errval);
+
+#endif /* _LIBFDT_H */
diff --git a/tests/arm64/common/basic/libfdt/libfdt_env.h b/tests/arm64/common/basic/libfdt/libfdt_env.h
new file mode 100644
index 0000000..18eec23
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/libfdt_env.h
@@ -0,0 +1,49 @@
+/*
+ * libfdt - Flat Device Tree manipulation (build/run environment adaptation)
+ * Copyright (C) 2007 Gerald Van Baren, Custom IDEAS,
vanb...@cideas.com
+ * Original version written by David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _LIBFDT_ENV_H
+#define _LIBFDT_ENV_H
+
+#include <arm_types.h>
+#include <arm_stdio.h>
+#include <arm_string.h>
+
+extern struct fdt_header *working_fdt; /* Pointer to the working fdt */
+
+#define fdt32_to_cpu(x) be32_to_cpu(x)
+#define cpu_to_fdt32(x) cpu_to_be32(x)
+#define fdt64_to_cpu(x) be64_to_cpu(x)
+#define cpu_to_fdt64(x) cpu_to_be64(x)
+
+#define memmove arm_memmove
+#define memcpy arm_memcpy
+#define memcmp arm_memcmp
+#define memchr arm_memchr
+#define memset arm_memset
+#define strchr arm_strchr
+#define strcpy arm_strcpy
+#define strcmp arm_strcmp
+#define strlen arm_strlen
+
+#define printf arm_printf
+#define sprintf arm_sprintf
+#define snprintf arm_snprintf
+
+#endif /* _LIBFDT_ENV_H */
diff --git a/tests/arm64/common/basic/libfdt/libfdt_internal.h b/tests/arm64/common/basic/libfdt/libfdt_internal.h
new file mode 100644
index 0000000..2a5e120
--- /dev/null
+++ b/tests/arm64/common/basic/libfdt/libfdt_internal.h
@@ -0,0 +1,95 @@
+#ifndef _LIBFDT_INTERNAL_H
+#define _LIBFDT_INTERNAL_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <libfdt/fdt.h>
+
+#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
+
+#define FDT_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = fdt_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+int _fdt_check_node_offset(const void *fdt, int offset);
+int _fdt_check_prop_offset(const void *fdt, int offset);
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
+int _fdt_node_end_offset(void *fdt, int nodeoffset);
+
+static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
+{
+ return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
+}
+
+static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
+{
+ return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
+}
+
+static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
+{
+ const struct fdt_reserve_entry *rsv_table =
+ (const struct fdt_reserve_entry *)
+ ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
+
+ return rsv_table + n;
+}
+static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
+{
+ return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
+}
+
+#define FDT_SW_MAGIC (~FDT_MAGIC)
+
+#endif /* _LIBFDT_INTERNAL_H */
diff --git a/tests/arm64/common/basic/pic/gic.c b/tests/arm64/common/basic/pic/gic.c
new file mode 100644
index 0000000..d5596e8
--- /dev/null
+++ b/tests/arm64/common/basic/pic/gic.c
@@ -0,0 +1,225 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file gic.c
+ * @brief ARM Generic Interrupt Controller
+ */
+
+#include <arm_io.h>
+#include <arm_stdio.h>
+#include <gic_config.h>
+#include <pic/gic.h>
+
+#define max(a,b) ((a) < (b) ? (b) : (a))
+
+struct gic_chip_data {
+ u32 irq_offset;
+ virtual_addr_t dist_base;
+ virtual_addr_t cpu_base;
+};
+
+static struct gic_chip_data gic_data[GIC_MAX_NR];
+
+static inline void gic_write(u32 val, virtual_addr_t addr)
+{
+ arm_writel(val, (void *)(addr));
+}
+
+static inline u32 gic_read(virtual_addr_t addr)
+{
+ return arm_readl((void *)(addr));
+}
+
+int gic_active_irq(u32 gic_nr)
+{
+ int ret = -1;
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ ret = gic_read(gic_data[gic_nr].cpu_base +
+ GIC_CPU_INTACK) & 0x3FF;
+ ret += gic_data[gic_nr].irq_offset;
+
+ return ret;
+}
+
+int gic_eoi_irq(u32 gic_nr, u32 irq)
+{
+// u32 mask = 1 << (irq % 32);
+ u32 gic_irq;
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ if (irq < gic_data[gic_nr].irq_offset) {
+ return -1;
+ }
+
+ gic_irq = irq - gic_data[gic_nr].irq_offset;
+
+ /*
+ *gic_write(mask, gic_data[gic_nr].dist_base +
+ * GIC_DIST_ENABLE_CLEAR + (gic_irq / 32) * 4);
+ */
+ gic_write(gic_irq, gic_data[gic_nr].cpu_base + GIC_CPU_EOI);
+ /*
+ *gic_write(mask, gic_data[gic_nr].dist_base +
+ * GIC_DIST_ENABLE_SET + (gic_irq / 32) * 4);
+ */
+
+ return 0;
+}
+
+int gic_mask(u32 gic_nr, u32 irq)
+{
+ u32 mask = 1 << (irq % 32);
+ u32 gic_irq;
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ if (irq < gic_data[gic_nr].irq_offset) {
+ return -1;
+ }
+
+ gic_irq = irq - gic_data[gic_nr].irq_offset;
+
+ gic_write(mask, gic_data[gic_nr].dist_base +
+ GIC_DIST_ENABLE_CLEAR + (gic_irq / 32) * 4);
+
+ return 0;
+}
+
+int gic_unmask(u32 gic_nr, u32 irq)
+{
+ u32 mask = 1 << (irq % 32);
+ u32 gic_irq;
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ if (irq < gic_data[gic_nr].irq_offset) {
+ return -1;
+ }
+
+ gic_irq = irq - gic_data[gic_nr].irq_offset;
+
+ gic_write(mask, gic_data[gic_nr].dist_base +
+ GIC_DIST_ENABLE_SET + (gic_irq / 32) * 4);
+
+ return 0;
+}
+
+int gic_dist_init(u32 gic_nr, virtual_addr_t base, u32 irq_start)
+{
+ unsigned int max_irq, i;
+ u32 cpumask = 1 << 0; /*smp_processor_id(); */
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ cpumask |= cpumask << 8;
+ cpumask |= cpumask << 16;
+
+ gic_data[gic_nr].dist_base = base;
+ gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
+
+ gic_write(0, base + GIC_DIST_CTRL);
+
+ /*
+ * Find out how many interrupts are supported.
+ */
+ max_irq = gic_read(base + GIC_DIST_CTR) & 0x1f;
+ max_irq = (max_irq + 1) * 32;
+
+ /*
+ * The GIC only supports up to 1020 interrupt sources.
+ * Limit this to either the architected maximum, or the
+ * platform maximum.
+ */
+ if (max_irq > max(1020, GIC_NR_IRQS))
+ max_irq = max(1020, GIC_NR_IRQS);
+
+ /*
+ * Set all global interrupts to be level triggered, active low.
+ */
+ for (i = 32; i < max_irq; i += 16)
+ gic_write(0, base + GIC_DIST_CONFIG + i * 4 / 16);
+
+ /*
+ * Set all global interrupts to this CPU only.
+ */
+ for (i = 32; i < max_irq; i += 4)
+ gic_write(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
+
+ /*
+ * Set priority on all interrupts.
+ */
+ for (i = 0; i < max_irq; i += 4)
+ gic_write(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
+
+ /*
+ * Disable all interrupts.
+ */
+ for (i = 0; i < max_irq; i += 32)
+ gic_write(0xffffffff,
+ base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
+
+ gic_write(1, base + GIC_DIST_CTRL);
+
+ return 0;
+}
+
+int gic_cpu_init(u32 gic_nr, virtual_addr_t base)
+{
+ int i;
+
+ if (GIC_MAX_NR <= gic_nr) {
+ return -1;
+ }
+
+ gic_data[gic_nr].cpu_base = base;
+
+ /*
+ * Deal with the banked PPI and SGI interrupts - disable all
+ * PPI interrupts, ensure all SGI interrupts are enabled.
+ */
+ gic_write(0xffff0000, gic_data[gic_nr].dist_base + GIC_DIST_ENABLE_CLEAR);
+ gic_write(0x0000ffff, gic_data[gic_nr].dist_base + GIC_DIST_ENABLE_SET);
+
+ /*
+ * Set priority on PPI and SGI interrupts
+ */
+ for (i = 0; i < 32; i += 4) {
+ gic_write(0xa0a0a0a0,
+ gic_data[gic_nr].dist_base + GIC_DIST_PRI + i * 4 / 4);
+ }
+
+
+ gic_write(0xf0, base + GIC_CPU_PRIMASK);
+ gic_write(1, base + GIC_CPU_CTRL);
+
+ return 0;
+}
diff --git a/tests/arm64/common/basic/pic/gic.h b/tests/arm64/common/basic/pic/gic.h
new file mode 100644
index 0000000..7f6e6d0
--- /dev/null
+++ b/tests/arm64/common/basic/pic/gic.h
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file gic.h
+ * @brief ARM Generic Interrupt Controller header
+ */
+#ifndef _GIC_H__
+#define _GIC_H__
+
+#include <arm_types.h>
+#include <arm_plat.h>
+
+#define GIC_CPU_CTRL 0x00
+#define GIC_CPU_PRIMASK 0x04
+#define GIC_CPU_BINPOINT 0x08
+#define GIC_CPU_INTACK 0x0c
+#define GIC_CPU_EOI 0x10
+#define GIC_CPU_RUNNINGPRI 0x14
+#define GIC_CPU_HIGHPRI 0x18
+
+#define GIC_DIST_CTRL 0x000
+#define GIC_DIST_CTR 0x004
+#define GIC_DIST_ENABLE_SET 0x100
+#define GIC_DIST_ENABLE_CLEAR 0x180
+#define GIC_DIST_PENDING_SET 0x200
+#define GIC_DIST_PENDING_CLEAR 0x280
+#define GIC_DIST_ACTIVE_BIT 0x300
+#define GIC_DIST_PRI 0x400
+#define GIC_DIST_TARGET 0x800
+#define GIC_DIST_CONFIG 0xc00
+#define GIC_DIST_SOFTINT 0xf00
+
+int gic_active_irq(u32 gic_nr);
+int gic_eoi_irq(u32 gic_nr, u32 irq);
+int gic_mask(u32 gic_nr, u32 irq);
+int gic_unmask(u32 gic_nr, u32 irq);
+int gic_dist_init(u32 gic_nr, virtual_addr_t base, u32 irq_start);
+int gic_cpu_init(u32 gic_nr, virtual_addr_t base);
+
+#endif
diff --git a/tests/arm64/common/basic/serial/pl01x.c b/tests/arm64/common/basic/serial/pl01x.c
new file mode 100644
index 0000000..fa6cee3
--- /dev/null
+++ b/tests/arm64/common/basic/serial/pl01x.c
@@ -0,0 +1,138 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file pl01x.c
+ * @brief source file for PrimeCell PL011/PL010 serial port driver.
+ */
+
+#include <arm_io.h>
+#include <arm_math.h>
+#include <serial/pl01x.h>
+
+void pl01x_putc(u64 base, u32 type, char ch)
+{
+ /* Wait until there is space in the FIFO */
+ while (arm_readl((void*)(base + UART_PL01x_FR)) & UART_PL01x_FR_TXFF);
+
+ /* Send the character */
+ arm_writel(ch, (void*)(base + UART_PL01x_DR));
+}
+
+char pl01x_getc(u64 base, u32 type)
+{
+ char data;
+
+ /* Wait until there is data in the FIFO */
+ while (arm_readl((void*)(base + UART_PL01x_FR)) & UART_PL01x_FR_RXFE);
+
+ data = arm_readl((void*)(base + UART_PL01x_DR));
+
+ /* Check for an error flag */
+ if (data & 0xFFFFFF00) {
+ /* Clear the error */
+ arm_writel(0xFFFFFFFF, (void*)(base + UART_PL01x_ECR));
+ return -1;
+ }
+
+ return data;
+}
+
+void pl01x_init(u64 base, u32 type, u32 baudrate, u32 input_clock)
+{
+ unsigned int divider;
+ unsigned int temp;
+ unsigned int remainder;
+ unsigned int fraction;
+
+ if(type==PL01X_TYPE_1) {
+ /* First, disable everything */
+ arm_writel(0x0, (void*)(base + UART_PL011_CR));
+
+ /*
+ * Set baud rate
+ *
+ * IBRD = UART_CLK / (16 * BAUD_RATE)
+ * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
+ * / (16 * BAUD_RATE))
+ */
+ temp = 16 * baudrate;
+ divider = arm_udiv32(input_clock, temp);
+ remainder = arm_umod32(input_clock, temp);
+ temp = arm_udiv32((8 * remainder), baudrate);
+ fraction = (temp >> 1) + (temp & 1);
+
+ arm_writel(divider, (void*)(base + UART_PL011_IBRD));
+ arm_writel(fraction, (void*)(base + UART_PL011_FBRD));
+
+ /* Set the UART to be 8 bits, 1 stop bit,
+ * no parity, fifo enabled
+ */
+ arm_writel((UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN),
+ (void*)(base + UART_PL011_LCRH));
+
+ /* Finally, enable the UART */
+ arm_writel((UART_PL011_CR_UARTEN |
+ UART_PL011_CR_TXE |
+ UART_PL011_CR_RXE),
+ (void*)(base + UART_PL011_CR));
+ } else {
+ /* First, disable everything */
+ arm_writel(0x0, (void*)(base + UART_PL010_CR));
+
+ /* Set baud rate */
+ switch (baudrate) {
+ case 9600:
+ divider = UART_PL010_BAUD_9600;
+ break;
+
+ case 19200:
+ divider = UART_PL010_BAUD_9600;
+ break;
+
+ case 38400:
+ divider = UART_PL010_BAUD_38400;
+ break;
+
+ case 57600:
+ divider = UART_PL010_BAUD_57600;
+ break;
+
+ case 115200:
+ divider = UART_PL010_BAUD_115200;
+ break;
+
+ default:
+ divider = UART_PL010_BAUD_38400;
+ }
+
+ arm_writel(((divider & 0xf00) >> 8),
+ (void*)(base + UART_PL010_LCRM));
+ arm_writel((divider & 0xff), (void*)(base + UART_PL010_LCRL));
+
+ /* Set the UART to be 8 bits, 1 stop bit,
+ * no parity, fifo enabled */
+ arm_writel((UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN),
+ (void*)(base + UART_PL010_LCRH));
+
+ /* Finally, enable the UART */
+ arm_writel((UART_PL010_CR_UARTEN),
+ (void*)(base + UART_PL010_CR));
+ }
+}
+
diff --git a/tests/arm64/common/basic/serial/pl01x.h b/tests/arm64/common/basic/serial/pl01x.h
new file mode 100644
index 0000000..39b6f77
--- /dev/null
+++ b/tests/arm64/common/basic/serial/pl01x.h
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) 2011 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file pl01x.h
+ * @brief Header file for PrimeCell PL011/PL010 serial port driver.
+ */
+
+#ifndef __PL01X_H_
+#define __PL01X_H_
+
+#include <arm_types.h>
+
+#define PL01X_TYPE_0 0
+#define PL01X_TYPE_1 1
+
+/*
+ * ARM PrimeCell UART's (PL010 & PL011)
+ * ------------------------------------
+ *
+ * Definitions common to both PL010 & PL011
+ *
+ */
+#define UART_PL01x_DR 0x00 /* Data read or written from the interface. */
+#define UART_PL01x_RSR 0x04 /* Receive status register (Read). */
+#define UART_PL01x_ECR 0x04 /* Error clear register (Write). */
+#define UART_PL01x_FR 0x18 /* Flag register (Read only). */
+
+#define UART_PL01x_RSR_OE 0x08
+#define UART_PL01x_RSR_BE 0x04
+#define UART_PL01x_RSR_PE 0x02
+#define UART_PL01x_RSR_FE 0x01
+
+#define UART_PL01x_FR_TXFE 0x80
+#define UART_PL01x_FR_RXFF 0x40
+#define UART_PL01x_FR_TXFF 0x20
+#define UART_PL01x_FR_RXFE 0x10
+#define UART_PL01x_FR_BUSY 0x08
+#define UART_PL01x_FR_TMSK (UART_PL01x_FR_TXFF + UART_PL01x_FR_BUSY)
+
+/*
+ * PL010 definitions
+ *
+ */
+#define UART_PL010_LCRH 0x08 /* Line control register, high byte. */
+#define UART_PL010_LCRM 0x0C /* Line control register, middle byte. */
+#define UART_PL010_LCRL 0x10 /* Line control register, low byte. */
+#define UART_PL010_CR 0x14 /* Control register. */
+#define UART_PL010_IIR 0x1C /* Interrupt indentification register (Read). */
+#define UART_PL010_ICR 0x1C /* Interrupt clear register (Write). */
+#define UART_PL010_ILPR 0x20 /* IrDA low power counter register. */
+
+#define UART_PL010_CR_LPE (1 << 7)
+#define UART_PL010_CR_RTIE (1 << 6)
+#define UART_PL010_CR_TIE (1 << 5)
+#define UART_PL010_CR_RIE (1 << 4)
+#define UART_PL010_CR_MSIE (1 << 3)
+#define UART_PL010_CR_IIRLP (1 << 2)
+#define UART_PL010_CR_SIREN (1 << 1)
+#define UART_PL010_CR_UARTEN (1 << 0)
+
+#define UART_PL010_LCRH_WLEN_8 (3 << 5)
+#define UART_PL010_LCRH_WLEN_7 (2 << 5)
+#define UART_PL010_LCRH_WLEN_6 (1 << 5)
+#define UART_PL010_LCRH_WLEN_5 (0 << 5)
+#define UART_PL010_LCRH_FEN (1 << 4)
+#define UART_PL010_LCRH_STP2 (1 << 3)
+#define UART_PL010_LCRH_EPS (1 << 2)
+#define UART_PL010_LCRH_PEN (1 << 1)
+#define UART_PL010_LCRH_BRK (1 << 0)
+
+
+#define UART_PL010_BAUD_460800 1
+#define UART_PL010_BAUD_230400 3
+#define UART_PL010_BAUD_115200 7
+#define UART_PL010_BAUD_57600 15
+#define UART_PL010_BAUD_38400 23
+#define UART_PL010_BAUD_19200 47
+#define UART_PL010_BAUD_14400 63
+#define UART_PL010_BAUD_9600 95
+#define UART_PL010_BAUD_4800 191
+#define UART_PL010_BAUD_2400 383
+#define UART_PL010_BAUD_1200 767
+/*
+ * PL011 definitions
+ *
+ */
+#define UART_PL011_IBRD 0x24
+#define UART_PL011_FBRD 0x28
+#define UART_PL011_LCRH 0x2C
+#define UART_PL011_CR 0x30
+#define UART_PL011_IMSC 0x38
+#define UART_PL011_PERIPH_ID0 0xFE0
+
+#define UART_PL011_LCRH_SPS (1 << 7)
+#define UART_PL011_LCRH_WLEN_8 (3 << 5)
+#define UART_PL011_LCRH_WLEN_7 (2 << 5)
+#define UART_PL011_LCRH_WLEN_6 (1 << 5)
+#define UART_PL011_LCRH_WLEN_5 (0 << 5)
+#define UART_PL011_LCRH_FEN (1 << 4)
+#define UART_PL011_LCRH_STP2 (1 << 3)
+#define UART_PL011_LCRH_EPS (1 << 2)
+#define UART_PL011_LCRH_PEN (1 << 1)
+#define UART_PL011_LCRH_BRK (1 << 0)
+
+#define UART_PL011_CR_CTSEN (1 << 15)
+#define UART_PL011_CR_RTSEN (1 << 14)
+#define UART_PL011_CR_OUT2 (1 << 13)
+#define UART_PL011_CR_OUT1 (1 << 12)
+#define UART_PL011_CR_RTS (1 << 11)
+#define UART_PL011_CR_DTR (1 << 10)
+#define UART_PL011_CR_RXE (1 << 9)
+#define UART_PL011_CR_TXE (1 << 8)
+#define UART_PL011_CR_LPE (1 << 7)
+#define UART_PL011_CR_IIRLP (1 << 2)
+#define UART_PL011_CR_SIREN (1 << 1)
+#define UART_PL011_CR_UARTEN (1 << 0)
+
+#define UART_PL011_IMSC_OEIM (1 << 10)
+#define UART_PL011_IMSC_BEIM (1 << 9)
+#define UART_PL011_IMSC_PEIM (1 << 8)
+#define UART_PL011_IMSC_FEIM (1 << 7)
+#define UART_PL011_IMSC_RTIM (1 << 6)
+#define UART_PL011_IMSC_TXIM (1 << 5)
+#define UART_PL011_IMSC_RXIM (1 << 4)
+#define UART_PL011_IMSC_DSRMIM (1 << 3)
+#define UART_PL011_IMSC_DCDMIM (1 << 2)
+#define UART_PL011_IMSC_CTSMIM (1 << 1)
+#define UART_PL011_IMSC_RIMIM (1 << 0)
+
+char pl01x_getc(u64 base, u32 type);
+void pl01x_putc(u64 base, u32 type, char ch);
+void pl01x_init(u64 base, u32 type, u32 baudrate, u32 input_clock);
+
+#endif /* __PL01X_H_ */
diff --git a/tests/arm64/common/basic/serial/virtio_console.c b/tests/arm64/common/basic/serial/virtio_console.c
new file mode 100644
index 0000000..7f964f3
--- /dev/null
+++ b/tests/arm64/common/basic/serial/virtio_console.c
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2013 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file virtio_console.c
+ * @brief Source file for Virtio Console serial port driver.
+ */
+
+#include <arm_io.h>
+#include <serial/virtio_console.h>
+
+void virtio_console_printch(physical_addr_t base, char ch)
+{
+ u32 tmp;
+ struct virtio_console_config *p = (void *)base + VIRTIO_MMIO_CONFIG;
+
+ tmp = arm_readl((void *)(base + VIRTIO_MMIO_DEVICE_ID));
+ if (tmp != VIRTIO_ID_CONSOLE) {
+ return;
+ }
+
+ tmp = arm_readl((void *)(base + VIRTIO_MMIO_HOST_FEATURES));
+ if (!(tmp & (1 << VIRTIO_CONSOLE_F_EMERG_WRITE))) {
+ return;
+ }
+
+ arm_writel(ch, &p->emerg_wr);
+}
+
+char virtio_console_getch(physical_addr_t base)
+{
+ u32 tmp;
+ struct virtio_console_config *p = (void *)base + VIRTIO_MMIO_CONFIG;
+
+ tmp = arm_readl((void *)(base + VIRTIO_MMIO_DEVICE_ID));
+ if (tmp != VIRTIO_ID_CONSOLE) {
+ return 0;
+ }
+
+ tmp = arm_readl((void *)(base + VIRTIO_MMIO_HOST_FEATURES));
+ if (!(tmp & (1 << VIRTIO_CONSOLE_F_EMERG_WRITE))) {
+ return 0;
+ }
+
+ while (!((tmp = arm_readl(&p->emerg_wr)) & (1 << 31))) ;
+
+ return (char)(tmp & 0xFFU);
+}
+
+int virtio_console_init(physical_addr_t base)
+{
+ /* Nothing to do here. */
+ return 0;
+}
+
diff --git a/tests/arm64/common/basic/serial/virtio_console.h b/tests/arm64/common/basic/serial/virtio_console.h
new file mode 100644
index 0000000..9f05992
--- /dev/null
+++ b/tests/arm64/common/basic/serial/virtio_console.h
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2013 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file virtio_console.h
+ * @brief Header file for Virtio Console serial port driver.
+ */
+
+#ifndef __VIRTIO_CONSOLE_H_
+#define __VIRTIO_CONSOLE_H_
+
+#include <arm_types.h>
+
+/* VirtIO MMIO */
+#define VIRTIO_MMIO_DEVICE_ID 0x008
+#define VIRTIO_MMIO_HOST_FEATURES 0x010
+#define VIRTIO_MMIO_CONFIG 0x100
+
+/* VirtIO Console */
+#define VIRTIO_ID_CONSOLE 3
+
+/* VirtIO Console Feature bits */
+#define VIRTIO_CONSOLE_F_SIZE 0
+#define VIRTIO_CONSOLE_F_MULTIPORT 1
+#define VIRTIO_CONSOLE_F_EMERG_WRITE 2
+
+struct virtio_console_config {
+ /* colums of the screens */
+ u16 cols;
+ /* rows of the screens */
+ u16 rows;
+ /* max. number of ports this device can hold */
+ u32 max_nr_ports;
+ /* emergency write register */
+ u32 emerg_wr;
+} __attribute__((packed));
+
+void virtio_console_printch(physical_addr_t base, char ch);
+char virtio_console_getch(physical_addr_t base);
+int virtio_console_init(physical_addr_t base);
+
+#endif /* __VIRTIO_CONSOLE_H_ */
diff --git a/tests/arm64/common/basic/timer/generic_timer.c b/tests/arm64/common/basic/timer/generic_timer.c
new file mode 100644
index 0000000..0d4e9af
--- /dev/null
+++ b/tests/arm64/common/basic/timer/generic_timer.c
@@ -0,0 +1,166 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file generic_timer.c
+ * @brief ARMv8 Generic Timer driver source
+ *
+ */
+
+#include <arm_irq.h>
+#include <arm_math.h>
+#include <arm_stdio.h>
+#include <arm_inline_asm.h>
+#include <timer/generic_timer.h>
+
+#define GENERIC_TIMER_CTRL_ENABLE (1 << 0)
+#define GENERIC_TIMER_CTRL_IT_MASK (1 << 1)
+#define GENERIC_TIMER_CTRL_IT_STAT (1 << 2)
+
+static u64 timer_irq_count;
+static u64 timer_irq_tcount;
+static u64 timer_irq_delay;
+static u64 timer_irq_tstamp;
+static u64 timer_freq;
+static u64 timer_period_ticks;
+static u64 timer_mult;
+static u32 timer_shift;
+
+void generic_timer_enable(void)
+{
+ unsigned long ctrl;
+
+ ctrl = mrs(cntv_ctl_el0);
+ ctrl |= GENERIC_TIMER_CTRL_ENABLE;
+ ctrl &= ~GENERIC_TIMER_CTRL_IT_MASK;
+ msr(cntv_ctl_el0, ctrl);
+}
+
+void generic_timer_disable(void)
+{
+ unsigned long ctrl;
+
+ ctrl = mrs(cntv_ctl_el0);
+ ctrl &= ~GENERIC_TIMER_CTRL_ENABLE;
+ msr(cntv_ctl_el0, ctrl);
+}
+
+void generic_timer_change_period(u32 usec)
+{
+ timer_period_ticks = ((timer_freq / 1000000) * usec);
+
+ msr(cntv_tval_el0, timer_period_ticks);
+}
+
+u64 generic_timer_irqcount(void)
+{
+ return timer_irq_count;
+}
+
+u64 generic_timer_irqdelay(void)
+{
+ return timer_irq_delay;
+}
+
+u64 generic_timer_timestamp(void)
+{
+ return (mrs(cntvct_el0) * timer_mult) >> timer_shift;
+}
+
+int generic_timer_irqhndl(u32 irq_no, struct pt_regs *regs)
+{
+ unsigned long ctrl;
+ u64 tstamp;
+
+ ctrl = mrs(cntv_ctl_el0);
+ if (ctrl & GENERIC_TIMER_CTRL_IT_STAT) {
+ ctrl |= GENERIC_TIMER_CTRL_IT_MASK;
+ msr(cntv_ctl_el0, ctrl);
+ }
+
+ timer_irq_count++;
+ timer_irq_tcount++;
+
+ tstamp = generic_timer_timestamp();
+ if (!timer_irq_tstamp) {
+ timer_irq_tstamp = tstamp;
+ }
+ if (timer_irq_tcount == 128) {
+ timer_irq_delay = (tstamp - timer_irq_tstamp) >> 7;
+ timer_irq_tcount = 0;
+ timer_irq_tstamp = tstamp;
+ }
+
+ ctrl = mrs(cntv_ctl_el0);
+ ctrl |= GENERIC_TIMER_CTRL_ENABLE;
+ ctrl &= ~GENERIC_TIMER_CTRL_IT_MASK;
+
+ msr(cntv_tval_el0, timer_period_ticks);
+ msr(cntv_ctl_el0, GENERIC_TIMER_CTRL_ENABLE);
+
+ return 0;
+}
+
+static void calc_mult_shift(u64 *mult, u32 *shift,
+ u32 from, u32 to, u32 maxsec)
+{
+ u64 tmp;
+ u32 sft, sftacc= 32;
+
+ /* Calculate the shift factor which is limiting
+ * the conversion range:
+ */
+ tmp = ((u64)maxsec * from) >> 32;
+ while (tmp) {
+ tmp >>=1;
+ sftacc--;
+ }
+
+ /* Find the conversion shift/mult pair which has the best
+ * accuracy and fits the maxsec conversion range:
+ */
+ for (sft = 32; sft > 0; sft--) {
+ tmp = (u64) to << sft;
+ tmp += from / 2;
+ tmp /= from;
+ if ((tmp >> sftacc) == 0)
+ break;
+ }
+ *mult = tmp;
+ *shift = sft;
+}
+
+int generic_timer_init(u32 usecs, u32 irq)
+{
+ timer_freq = mrs(cntfrq_el0);
+ if (timer_freq == 0) {
+ /* Assume 100 Mhz clock if cntfrq_el0 not programmed */
+ timer_freq = 100000000;
+ }
+
+ calc_mult_shift(&timer_mult, &timer_shift, timer_freq, 1000000000, 1);
+
+ timer_period_ticks = ((timer_freq / 1000000) * usecs);
+
+ arm_irq_register(irq, &generic_timer_irqhndl);
+
+ msr(cntv_tval_el0, timer_period_ticks);
+ msr(cntv_ctl_el0, GENERIC_TIMER_CTRL_IT_MASK);
+
+ return 0;
+}
diff --git a/tests/arm64/common/basic/timer/generic_timer.h b/tests/arm64/common/basic/timer/generic_timer.h
new file mode 100644
index 0000000..471048b
--- /dev/null
+++ b/tests/arm64/common/basic/timer/generic_timer.h
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file generic_timer.h
+ * @brief ARMv8 Generic Timer Header
+ */
+#ifndef _ARM_GENERIC_TIMER_H__
+#define _ARM_GENERIC_TIMER_H__
+
+#include <arm_types.h>
+
+void generic_timer_enable(void);
+void generic_timer_disable(void);
+u64 generic_timer_irqcount(void);
+u64 generic_timer_irqdelay(void);
+u64 generic_timer_timestamp(void);
+void generic_timer_change_period(u32 usecs);
+int generic_timer_init(u32 usecs, u32 irq);
+
+#endif
diff --git a/tests/arm64/common/busybox/README b/tests/arm64/common/busybox/README
new file mode 100644
index 0000000..9e72798
--- /dev/null
+++ b/tests/arm64/common/busybox/README
@@ -0,0 +1,38 @@
+ BusyBox RootFS for ARM64 Guest
+
+BusyBox provides several stripped-down Unix tools in a single executable. It
+runs in a variety of POSIX environments such as Linux, Android,[6] FreeBSD[7]
+and others, such as proprietary kernels, although many of the tools it provides
+are designed to work with interfaces provided by the Linux kernel. It was
+created for embedded operating systems with very limited resources. It is
+released under the terms of the GNU General Public License. For more info
+read the BusyBox wiki page
http://en.wikipedia.org/wiki/BusyBox
+
+Please follow the steps below to build a RAMDISK using BusyBox, to be used as
+RootFS for ARM64 Linux guest:
+
+ [1. Build environment for Xvisor]
+ # CROSS_COMPILE=aarch64-linux-gnu-
+
+ [2. GoTo Busybox source directory]
+ # cd <busybox_source_directory>
+
+ [3. Copy defconfig to Busybox source directory]
+ # cp <xvisor_source_directory>/tests/arm64/busybox/busybox-<busybox_version>_defconfig .config
+
+ [4. Configure Busybox source]
+ # make oldconfig
+
+ [5. Build Busybox RootFS]
+ # make install
+
+ [6. Change ownership of installed RootFS]
+ # sudo chown -R root:root ./_install
+
+ [7. Create RootFS image]
+ # fakeroot /bin/bash -c "genext2fs -b 5120 -N 1024 -D <xvisor_source_directory>/tests/arm64/common/busybox/busybox_dev.txt -d ./_install <busybox_rootfs_directory>/rootfs64.img"
+
+ (Note: <busybox_rootfs_directory>/rootfs64.img is our final RAMDISK)
+ (Note: replace all <> brackets based on your workspace)
+ (Note: you are free to the change ordering of above steps based on your workspace)
+
diff --git a/tests/arm64/common/busybox/busybox-1.21.0_defconfig b/tests/arm64/common/busybox/busybox-1.21.0_defconfig
new file mode 100644
index 0000000..9aacf0c
--- /dev/null
+++ b/tests/arm64/common/busybox/busybox-1.21.0_defconfig
@@ -0,0 +1,1034 @@
+#
+# Automatically generated make config: don't edit
+# Busybox version: 1.21.0
+# Sun Sep 1 20:28:08 2013
+#
+CONFIG_HAVE_DOT_CONFIG=y
+
+#
+# Busybox Settings
+#
+
+#
+# General Configuration
+#
+# CONFIG_DESKTOP is not set
+CONFIG_EXTRA_COMPAT=y
+CONFIG_INCLUDE_SUSv2=y
+# CONFIG_USE_PORTABLE_CODE is not set
+CONFIG_PLATFORM_LINUX=y
+CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
+# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
+# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
+CONFIG_SHOW_USAGE=y
+CONFIG_FEATURE_VERBOSE_USAGE=y
+CONFIG_FEATURE_COMPRESS_USAGE=y
+CONFIG_FEATURE_INSTALLER=y
+# CONFIG_INSTALL_NO_USR is not set
+# CONFIG_LOCALE_SUPPORT is not set
+# CONFIG_UNICODE_SUPPORT is not set
+# CONFIG_UNICODE_USING_LOCALE is not set
+# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set
+CONFIG_SUBST_WCHAR=0
+CONFIG_LAST_SUPPORTED_WCHAR=0
+# CONFIG_UNICODE_COMBINING_WCHARS is not set
+# CONFIG_UNICODE_WIDE_WCHARS is not set
+# CONFIG_UNICODE_BIDI_SUPPORT is not set
+# CONFIG_UNICODE_NEUTRAL_TABLE is not set
+# CONFIG_UNICODE_PRESERVE_BROKEN is not set
+CONFIG_LONG_OPTS=y
+CONFIG_FEATURE_DEVPTS=y
+# CONFIG_FEATURE_CLEAN_UP is not set
+CONFIG_FEATURE_UTMP=y
+CONFIG_FEATURE_WTMP=y
+# CONFIG_FEATURE_PIDFILE is not set
+CONFIG_PID_FILE_PATH=""
+CONFIG_FEATURE_SUID=y
+CONFIG_FEATURE_SUID_CONFIG=y
+CONFIG_FEATURE_SUID_CONFIG_QUIET=y
+# CONFIG_SELINUX is not set
+CONFIG_FEATURE_PREFER_APPLETS=y
+CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
+CONFIG_FEATURE_SYSLOG=y
+# CONFIG_FEATURE_HAVE_RPC is not set
+
+#
+# Build Options
+#
+CONFIG_STATIC=y
+# CONFIG_PIE is not set
+# CONFIG_NOMMU is not set
+# CONFIG_BUILD_LIBBUSYBOX is not set
+# CONFIG_FEATURE_INDIVIDUAL is not set
+# CONFIG_FEATURE_SHARED_BUSYBOX is not set
+CONFIG_LFS=y
+CONFIG_CROSS_COMPILER_PREFIX="aarch64-linux-gnu-"
+CONFIG_SYSROOT=""
+CONFIG_EXTRA_CFLAGS="-mlittle-endian"
+CONFIG_EXTRA_LDFLAGS=""
+CONFIG_EXTRA_LDLIBS=""
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_DEBUG_PESSIMIZE is not set
+# CONFIG_WERROR is not set
+CONFIG_NO_DEBUG_LIB=y
+# CONFIG_DMALLOC is not set
+# CONFIG_EFENCE is not set
+
+#
+# Installation Options ("make install" behavior)
+#
+CONFIG_INSTALL_APPLET_SYMLINKS=y
+# CONFIG_INSTALL_APPLET_HARDLINKS is not set
+# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set
+# CONFIG_INSTALL_APPLET_DONT is not set
+# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set
+# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set
+# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set
+CONFIG_PREFIX="./_install"
+
+#
+# Busybox Library Tuning
+#
+CONFIG_FEATURE_SYSTEMD=y
+CONFIG_FEATURE_RTMINMAX=y
+CONFIG_PASSWORD_MINLEN=6
+CONFIG_MD5_SMALL=1
+CONFIG_SHA3_SMALL=1
+CONFIG_FEATURE_FAST_TOP=y
+CONFIG_FEATURE_ETC_NETWORKS=y
+CONFIG_FEATURE_USE_TERMIOS=y
+CONFIG_FEATURE_EDITING=y
+CONFIG_FEATURE_EDITING_MAX_LEN=1024
+CONFIG_FEATURE_EDITING_VI=y
+CONFIG_FEATURE_EDITING_HISTORY=15
+# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set
+# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set
+# CONFIG_FEATURE_REVERSE_SEARCH is not set
+CONFIG_FEATURE_TAB_COMPLETION=y
+CONFIG_FEATURE_USERNAME_COMPLETION=y
+CONFIG_FEATURE_EDITING_FANCY_PROMPT=y
+CONFIG_FEATURE_EDITING_ASK_TERMINAL=y
+CONFIG_FEATURE_NON_POSIX_CP=y
+CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y
+CONFIG_FEATURE_COPYBUF_KB=4
+CONFIG_FEATURE_SKIP_ROOTFS=y
+CONFIG_MONOTONIC_SYSCALL=y
+CONFIG_IOCTL_HEX2STR_ERROR=y
+CONFIG_FEATURE_HWIB=y
+
+#
+# Applets
+#
+
+#
+# Archival Utilities
+#
+# CONFIG_FEATURE_SEAMLESS_XZ is not set
+# CONFIG_FEATURE_SEAMLESS_LZMA is not set
+# CONFIG_FEATURE_SEAMLESS_BZ2 is not set
+# CONFIG_FEATURE_SEAMLESS_GZ is not set
+# CONFIG_FEATURE_SEAMLESS_Z is not set
+# CONFIG_AR is not set
+# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
+# CONFIG_FEATURE_AR_CREATE is not set
+# CONFIG_BUNZIP2 is not set
+# CONFIG_BZIP2 is not set
+# CONFIG_CPIO is not set
+# CONFIG_FEATURE_CPIO_O is not set
+# CONFIG_FEATURE_CPIO_P is not set
+# CONFIG_DPKG is not set
+# CONFIG_DPKG_DEB is not set
+# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
+# CONFIG_GUNZIP is not set
+# CONFIG_GZIP is not set
+# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set
+CONFIG_GZIP_FAST=0
+# CONFIG_LZOP is not set
+# CONFIG_LZOP_COMPR_HIGH is not set
+# CONFIG_RPM2CPIO is not set
+# CONFIG_RPM is not set
+# CONFIG_TAR is not set
+# CONFIG_FEATURE_TAR_CREATE is not set
+# CONFIG_FEATURE_TAR_AUTODETECT is not set
+# CONFIG_FEATURE_TAR_FROM is not set
+# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set
+# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set
+# CONFIG_FEATURE_TAR_GNU_EXTENSIONS is not set
+# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
+# CONFIG_FEATURE_TAR_TO_COMMAND is not set
+# CONFIG_FEATURE_TAR_UNAME_GNAME is not set
+# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set
+# CONFIG_FEATURE_TAR_SELINUX is not set
+# CONFIG_UNCOMPRESS is not set
+# CONFIG_UNLZMA is not set
+# CONFIG_FEATURE_LZMA_FAST is not set
+# CONFIG_LZMA is not set
+# CONFIG_UNXZ is not set
+# CONFIG_XZ is not set
+# CONFIG_UNZIP is not set
+
+#
+# Coreutils
+#
+CONFIG_BASENAME=y
+CONFIG_CAT=y
+CONFIG_DATE=y
+CONFIG_FEATURE_DATE_ISOFMT=y
+# CONFIG_FEATURE_DATE_NANO is not set
+CONFIG_FEATURE_DATE_COMPAT=y
+CONFIG_HOSTID=y
+CONFIG_ID=y
+CONFIG_GROUPS=y
+CONFIG_TEST=y
+CONFIG_FEATURE_TEST_64=y
+CONFIG_TOUCH=y
+CONFIG_FEATURE_TOUCH_SUSV3=y
+CONFIG_TR=y
+CONFIG_FEATURE_TR_CLASSES=y
+CONFIG_FEATURE_TR_EQUIV=y
+CONFIG_BASE64=y
+CONFIG_WHO=y
+CONFIG_USERS=y
+CONFIG_CAL=y
+CONFIG_CATV=y
+CONFIG_CHGRP=y
+CONFIG_CHMOD=y
+CONFIG_CHOWN=y
+CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y
+CONFIG_CHROOT=y
+CONFIG_CKSUM=y
+CONFIG_COMM=y
+CONFIG_CP=y
+CONFIG_FEATURE_CP_LONG_OPTIONS=y
+CONFIG_CUT=y
+CONFIG_DD=y
+CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
+CONFIG_FEATURE_DD_THIRD_STATUS_LINE=y
+CONFIG_FEATURE_DD_IBS_OBS=y
+CONFIG_DF=y
+CONFIG_FEATURE_DF_FANCY=y
+CONFIG_DIRNAME=y
+CONFIG_DOS2UNIX=y
+CONFIG_UNIX2DOS=y
+CONFIG_DU=y
+CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y
+CONFIG_ECHO=y
+CONFIG_FEATURE_FANCY_ECHO=y
+CONFIG_ENV=y
+CONFIG_FEATURE_ENV_LONG_OPTIONS=y
+CONFIG_EXPAND=y
+CONFIG_FEATURE_EXPAND_LONG_OPTIONS=y
+CONFIG_EXPR=y
+CONFIG_EXPR_MATH_SUPPORT_64=y
+CONFIG_FALSE=y
+CONFIG_FOLD=y
+CONFIG_FSYNC=y
+CONFIG_HEAD=y
+CONFIG_FEATURE_FANCY_HEAD=y
+CONFIG_INSTALL=y
+CONFIG_FEATURE_INSTALL_LONG_OPTIONS=y
+CONFIG_LN=y
+CONFIG_LOGNAME=y
+CONFIG_LS=y
+CONFIG_FEATURE_LS_FILETYPES=y
+CONFIG_FEATURE_LS_FOLLOWLINKS=y
+CONFIG_FEATURE_LS_RECURSIVE=y
+CONFIG_FEATURE_LS_SORTFILES=y
+CONFIG_FEATURE_LS_TIMESTAMPS=y
+CONFIG_FEATURE_LS_USERNAME=y
+CONFIG_FEATURE_LS_COLOR=y
+CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
+CONFIG_MD5SUM=y
+CONFIG_MKDIR=y
+CONFIG_FEATURE_MKDIR_LONG_OPTIONS=y
+CONFIG_MKFIFO=y
+CONFIG_MKNOD=y
+CONFIG_MV=y
+CONFIG_FEATURE_MV_LONG_OPTIONS=y
+CONFIG_NICE=y
+CONFIG_NOHUP=y
+CONFIG_OD=y
+CONFIG_PRINTENV=y
+CONFIG_PRINTF=y
+CONFIG_PWD=y
+CONFIG_READLINK=y
+CONFIG_FEATURE_READLINK_FOLLOW=y
+CONFIG_REALPATH=y
+CONFIG_RM=y
+CONFIG_RMDIR=y
+CONFIG_FEATURE_RMDIR_LONG_OPTIONS=y
+CONFIG_SEQ=y
+CONFIG_SHA1SUM=y
+CONFIG_SHA256SUM=y
+CONFIG_SHA512SUM=y
+CONFIG_SHA3SUM=y
+CONFIG_SLEEP=y
+CONFIG_FEATURE_FANCY_SLEEP=y
+CONFIG_FEATURE_FLOAT_SLEEP=y
+CONFIG_SORT=y
+CONFIG_FEATURE_SORT_BIG=y
+CONFIG_SPLIT=y
+CONFIG_FEATURE_SPLIT_FANCY=y
+CONFIG_STAT=y
+CONFIG_FEATURE_STAT_FORMAT=y
+CONFIG_STTY=y
+CONFIG_SUM=y
+CONFIG_SYNC=y
+CONFIG_TAC=y
+CONFIG_TAIL=y
+CONFIG_FEATURE_FANCY_TAIL=y
+CONFIG_TEE=y
+CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
+CONFIG_TRUE=y
+CONFIG_TTY=y
+CONFIG_UNAME=y
+CONFIG_UNEXPAND=y
+CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS=y
+CONFIG_UNIQ=y
+CONFIG_USLEEP=y
+CONFIG_UUDECODE=y
+CONFIG_UUENCODE=y
+CONFIG_WC=y
+CONFIG_FEATURE_WC_LARGE=y
+CONFIG_WHOAMI=y
+CONFIG_YES=y
+
+#
+# Common options for cp and mv
+#
+CONFIG_FEATURE_PRESERVE_HARDLINKS=y
+
+#
+# Common options for ls, more and telnet
+#
+CONFIG_FEATURE_AUTOWIDTH=y
+
+#
+# Common options for df, du, ls
+#
+CONFIG_FEATURE_HUMAN_READABLE=y
+
+#
+# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum
+#
+CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
+
+#
+# Console Utilities
+#
+CONFIG_CHVT=y
+CONFIG_FGCONSOLE=y
+CONFIG_CLEAR=y
+CONFIG_DEALLOCVT=y
+CONFIG_DUMPKMAP=y
+CONFIG_KBD_MODE=y
+CONFIG_LOADFONT=y
+CONFIG_LOADKMAP=y
+CONFIG_OPENVT=y
+CONFIG_RESET=y
+CONFIG_RESIZE=y
+CONFIG_FEATURE_RESIZE_PRINT=y
+CONFIG_SETCONSOLE=y
+CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y
+CONFIG_SETFONT=y
+CONFIG_FEATURE_SETFONT_TEXTUAL_MAP=y
+CONFIG_DEFAULT_SETFONT_DIR=""
+CONFIG_SETKEYCODES=y
+CONFIG_SETLOGCONS=y
+CONFIG_SHOWKEY=y
+
+#
+# Common options for loadfont and setfont
+#
+CONFIG_FEATURE_LOADFONT_PSF2=y
+CONFIG_FEATURE_LOADFONT_RAW=y
+
+#
+# Debian Utilities
+#
+# CONFIG_MKTEMP is not set
+# CONFIG_PIPE_PROGRESS is not set
+# CONFIG_RUN_PARTS is not set
+# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set
+# CONFIG_FEATURE_RUN_PARTS_FANCY is not set
+# CONFIG_START_STOP_DAEMON is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
+CONFIG_WHICH=y
+
+#
+# Editors
+#
+CONFIG_PATCH=y
+CONFIG_VI=y
+CONFIG_FEATURE_VI_MAX_LEN=4096
+CONFIG_FEATURE_VI_8BIT=y
+CONFIG_FEATURE_VI_COLON=y
+CONFIG_FEATURE_VI_YANKMARK=y
+CONFIG_FEATURE_VI_SEARCH=y
+# CONFIG_FEATURE_VI_REGEX_SEARCH is not set
+CONFIG_FEATURE_VI_USE_SIGNALS=y
+CONFIG_FEATURE_VI_DOT_CMD=y
+CONFIG_FEATURE_VI_READONLY=y
+CONFIG_FEATURE_VI_SETOPTS=y
+CONFIG_FEATURE_VI_SET=y
+CONFIG_FEATURE_VI_WIN_RESIZE=y
+CONFIG_FEATURE_VI_ASK_TERMINAL=y
+CONFIG_AWK=y
+CONFIG_FEATURE_AWK_LIBM=y
+CONFIG_CMP=y
+CONFIG_DIFF=y
+CONFIG_FEATURE_DIFF_LONG_OPTIONS=y
+CONFIG_FEATURE_DIFF_DIR=y
+CONFIG_ED=y
+CONFIG_SED=y
+CONFIG_FEATURE_ALLOW_EXEC=y
+
+#
+# Finding Utilities
+#
+CONFIG_FIND=y
+CONFIG_FEATURE_FIND_PRINT0=y
+CONFIG_FEATURE_FIND_MTIME=y
+CONFIG_FEATURE_FIND_MMIN=y
+CONFIG_FEATURE_FIND_PERM=y
+CONFIG_FEATURE_FIND_TYPE=y
+CONFIG_FEATURE_FIND_XDEV=y
+CONFIG_FEATURE_FIND_MAXDEPTH=y
+CONFIG_FEATURE_FIND_NEWER=y
+CONFIG_FEATURE_FIND_INUM=y
+CONFIG_FEATURE_FIND_EXEC=y
+CONFIG_FEATURE_FIND_USER=y
+CONFIG_FEATURE_FIND_GROUP=y
+CONFIG_FEATURE_FIND_NOT=y
+CONFIG_FEATURE_FIND_DEPTH=y
+CONFIG_FEATURE_FIND_PAREN=y
+CONFIG_FEATURE_FIND_SIZE=y
+CONFIG_FEATURE_FIND_PRUNE=y
+CONFIG_FEATURE_FIND_DELETE=y
+CONFIG_FEATURE_FIND_PATH=y
+CONFIG_FEATURE_FIND_REGEX=y
+# CONFIG_FEATURE_FIND_CONTEXT is not set
+CONFIG_FEATURE_FIND_LINKS=y
+CONFIG_GREP=y
+CONFIG_FEATURE_GREP_EGREP_ALIAS=y
+CONFIG_FEATURE_GREP_FGREP_ALIAS=y
+CONFIG_FEATURE_GREP_CONTEXT=y
+CONFIG_XARGS=y
+CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
+CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
+CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
+CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
+
+#
+# Init Utilities
+#
+CONFIG_BOOTCHARTD=y
+CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER=y
+CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE=y
+CONFIG_HALT=y
+# CONFIG_FEATURE_CALL_TELINIT is not set
+CONFIG_TELINIT_PATH=""
+CONFIG_INIT=y
+CONFIG_FEATURE_USE_INITTAB=y
+CONFIG_FEATURE_KILL_REMOVED=y
+CONFIG_FEATURE_KILL_DELAY=1
+CONFIG_FEATURE_INIT_SCTTY=y
+CONFIG_FEATURE_INIT_SYSLOG=y
+CONFIG_FEATURE_EXTRA_QUIET=y
+CONFIG_FEATURE_INIT_COREDUMPS=y
+CONFIG_FEATURE_INITRD=y
+CONFIG_INIT_TERMINAL_TYPE="linux"
+CONFIG_MESG=y
+CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
+
+#
+# Login/Password Management Utilities
+#
+CONFIG_ADD_SHELL=y
+CONFIG_REMOVE_SHELL=y
+CONFIG_FEATURE_SHADOWPASSWDS=y
+CONFIG_USE_BB_PWD_GRP=y
+CONFIG_USE_BB_SHADOW=y
+CONFIG_USE_BB_CRYPT=y
+CONFIG_USE_BB_CRYPT_SHA=y
+CONFIG_ADDUSER=y
+CONFIG_FEATURE_ADDUSER_LONG_OPTIONS=y
+CONFIG_FEATURE_CHECK_NAMES=y
+CONFIG_FIRST_SYSTEM_ID=100
+CONFIG_LAST_SYSTEM_ID=999
+CONFIG_ADDGROUP=y
+CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS=y
+CONFIG_FEATURE_ADDUSER_TO_GROUP=y
+CONFIG_DELUSER=y
+CONFIG_DELGROUP=y
+CONFIG_FEATURE_DEL_USER_FROM_GROUP=y
+CONFIG_GETTY=y
+CONFIG_LOGIN=y
+# CONFIG_LOGIN_SESSION_AS_CHILD is not set
+# CONFIG_PAM is not set
+CONFIG_LOGIN_SCRIPTS=y
+CONFIG_FEATURE_NOLOGIN=y
+CONFIG_FEATURE_SECURETTY=y
+CONFIG_PASSWD=y
+CONFIG_FEATURE_PASSWD_WEAK_CHECK=y
+CONFIG_CRYPTPW=y
+CONFIG_CHPASSWD=y
+CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="des"
+CONFIG_SU=y
+CONFIG_FEATURE_SU_SYSLOG=y
+CONFIG_FEATURE_SU_CHECKS_SHELLS=y
+CONFIG_SULOGIN=y
+CONFIG_VLOCK=y
+
+#
+# Linux Ext2 FS Progs
+#
+CONFIG_CHATTR=y
+CONFIG_FSCK=y
+CONFIG_LSATTR=y
+# CONFIG_TUNE2FS is not set
+
+#
+# Linux Module Utilities
+#
+CONFIG_MODINFO=y
+CONFIG_MODPROBE_SMALL=y
+CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE=y
+CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
+# CONFIG_INSMOD is not set
+# CONFIG_RMMOD is not set
+# CONFIG_LSMOD is not set
+# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
+# CONFIG_MODPROBE is not set
+# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
+# CONFIG_DEPMOD is not set
+
+#
+# Options common to multiple modutils
+#
+# CONFIG_FEATURE_2_4_MODULES is not set
+CONFIG_FEATURE_INSMOD_TRY_MMAP=y
+# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
+# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
+# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
+# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
+# CONFIG_FEATURE_MODUTILS_ALIAS is not set
+# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
+CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
+CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
+
+#
+# Linux System Utilities
+#
+# CONFIG_BLOCKDEV is not set
+# CONFIG_MDEV is not set
+# CONFIG_FEATURE_MDEV_CONF is not set
+# CONFIG_FEATURE_MDEV_RENAME is not set
+# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set
+# CONFIG_FEATURE_MDEV_EXEC is not set
+# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set
+# CONFIG_REV is not set
+# CONFIG_ACPID is not set
+# CONFIG_FEATURE_ACPID_COMPAT is not set
+# CONFIG_BLKID is not set
+# CONFIG_FEATURE_BLKID_TYPE is not set
+CONFIG_DMESG=y
+CONFIG_FEATURE_DMESG_PRETTY=y
+# CONFIG_FBSET is not set
+# CONFIG_FEATURE_FBSET_FANCY is not set
+# CONFIG_FEATURE_FBSET_READMODE is not set
+# CONFIG_FDFLUSH is not set
+# CONFIG_FDFORMAT is not set
+# CONFIG_FDISK is not set
+# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set
+# CONFIG_FEATURE_FDISK_WRITABLE is not set
+# CONFIG_FEATURE_AIX_LABEL is not set
+# CONFIG_FEATURE_SGI_LABEL is not set
+# CONFIG_FEATURE_SUN_LABEL is not set
+# CONFIG_FEATURE_OSF_LABEL is not set
+# CONFIG_FEATURE_GPT_LABEL is not set
+# CONFIG_FEATURE_FDISK_ADVANCED is not set
+# CONFIG_FINDFS is not set
+# CONFIG_FLOCK is not set
+# CONFIG_FREERAMDISK is not set
+# CONFIG_FSCK_MINIX is not set
+CONFIG_MKFS_EXT2=y
+# CONFIG_MKFS_MINIX is not set
+# CONFIG_FEATURE_MINIX2 is not set
+# CONFIG_MKFS_REISER is not set
+# CONFIG_MKFS_VFAT is not set
+# CONFIG_GETOPT is not set
+# CONFIG_FEATURE_GETOPT_LONG is not set
+CONFIG_HEXDUMP=y
+CONFIG_FEATURE_HEXDUMP_REVERSE=y
+CONFIG_HD=y
+# CONFIG_HWCLOCK is not set
+# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set
+# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set
+# CONFIG_IPCRM is not set
+# CONFIG_IPCS is not set
+# CONFIG_LOSETUP is not set
+# CONFIG_LSPCI is not set
+# CONFIG_LSUSB is not set
+# CONFIG_MKSWAP is not set
+# CONFIG_FEATURE_MKSWAP_UUID is not set
+# CONFIG_MORE is not set
+CONFIG_MOUNT=y
+CONFIG_FEATURE_MOUNT_FAKE=y
+CONFIG_FEATURE_MOUNT_VERBOSE=y
+# CONFIG_FEATURE_MOUNT_HELPERS is not set
+CONFIG_FEATURE_MOUNT_LABEL=y
+# CONFIG_FEATURE_MOUNT_NFS is not set
+CONFIG_FEATURE_MOUNT_CIFS=y
+CONFIG_FEATURE_MOUNT_FLAGS=y
+CONFIG_FEATURE_MOUNT_FSTAB=y
+# CONFIG_PIVOT_ROOT is not set
+# CONFIG_RDATE is not set
+# CONFIG_RDEV is not set
+# CONFIG_READPROFILE is not set
+# CONFIG_RTCWAKE is not set
+# CONFIG_SCRIPT is not set
+# CONFIG_SCRIPTREPLAY is not set
+# CONFIG_SETARCH is not set
+# CONFIG_SWAPONOFF is not set
+# CONFIG_FEATURE_SWAPON_PRI is not set
+CONFIG_SWITCH_ROOT=y
+CONFIG_UMOUNT=y
+CONFIG_FEATURE_UMOUNT_ALL=y
+
+#
+# Common options for mount/umount
+#
+CONFIG_FEATURE_MOUNT_LOOP=y
+CONFIG_FEATURE_MOUNT_LOOP_CREATE=y
+# CONFIG_FEATURE_MTAB_SUPPORT is not set
+CONFIG_VOLUMEID=y
+
+#
+# Filesystem/Volume identification
+#
+CONFIG_FEATURE_VOLUMEID_EXT=y
+CONFIG_FEATURE_VOLUMEID_BTRFS=y
+CONFIG_FEATURE_VOLUMEID_REISERFS=y
+CONFIG_FEATURE_VOLUMEID_FAT=y
+CONFIG_FEATURE_VOLUMEID_EXFAT=y
+CONFIG_FEATURE_VOLUMEID_HFS=y
+CONFIG_FEATURE_VOLUMEID_JFS=y
+CONFIG_FEATURE_VOLUMEID_XFS=y
+CONFIG_FEATURE_VOLUMEID_NILFS=y
+CONFIG_FEATURE_VOLUMEID_NTFS=y
+CONFIG_FEATURE_VOLUMEID_ISO9660=y
+CONFIG_FEATURE_VOLUMEID_UDF=y
+CONFIG_FEATURE_VOLUMEID_LUKS=y
+CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y
+CONFIG_FEATURE_VOLUMEID_CRAMFS=y
+CONFIG_FEATURE_VOLUMEID_ROMFS=y
+# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set
+CONFIG_FEATURE_VOLUMEID_SYSV=y
+CONFIG_FEATURE_VOLUMEID_OCFS2=y
+CONFIG_FEATURE_VOLUMEID_LINUXRAID=y
+
+#
+# Miscellaneous Utilities
+#
+# CONFIG_CONSPY is not set
+CONFIG_LESS=y
+CONFIG_FEATURE_LESS_MAXLINES=9999999
+CONFIG_FEATURE_LESS_BRACKETS=y
+CONFIG_FEATURE_LESS_FLAGS=y
+CONFIG_FEATURE_LESS_MARKS=y
+CONFIG_FEATURE_LESS_REGEXP=y
+CONFIG_FEATURE_LESS_WINCH=y
+CONFIG_FEATURE_LESS_ASK_TERMINAL=y
+CONFIG_FEATURE_LESS_DASHCMD=y
+CONFIG_FEATURE_LESS_LINENUMS=y
+# CONFIG_NANDWRITE is not set
+# CONFIG_NANDDUMP is not set
+CONFIG_SETSERIAL=y
+# CONFIG_UBIATTACH is not set
+# CONFIG_UBIDETACH is not set
+# CONFIG_UBIMKVOL is not set
+# CONFIG_UBIRMVOL is not set
+# CONFIG_UBIRSVOL is not set
+# CONFIG_UBIUPDATEVOL is not set
+# CONFIG_ADJTIMEX is not set
+# CONFIG_BBCONFIG is not set
+# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set
+# CONFIG_BEEP is not set
+CONFIG_FEATURE_BEEP_FREQ=0
+CONFIG_FEATURE_BEEP_LENGTH_MS=0
+# CONFIG_CHAT is not set
+# CONFIG_FEATURE_CHAT_NOFAIL is not set
+# CONFIG_FEATURE_CHAT_TTY_HIFI is not set
+# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set
+# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set
+# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set
+# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set
+# CONFIG_FEATURE_CHAT_CLR_ABORT is not set
+# CONFIG_CHRT is not set
+# CONFIG_CROND is not set
+# CONFIG_FEATURE_CROND_D is not set
+# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
+CONFIG_FEATURE_CROND_DIR=""
+# CONFIG_CRONTAB is not set
+# CONFIG_DC is not set
+# CONFIG_FEATURE_DC_LIBM is not set
+# CONFIG_DEVFSD is not set
+# CONFIG_DEVFSD_MODLOAD is not set
+# CONFIG_DEVFSD_FG_NP is not set
+# CONFIG_DEVFSD_VERBOSE is not set
+# CONFIG_FEATURE_DEVFS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_EJECT is not set
+# CONFIG_FEATURE_EJECT_SCSI is not set
+# CONFIG_FBSPLASH is not set
+# CONFIG_FLASHCP is not set
+# CONFIG_FLASH_LOCK is not set
+# CONFIG_FLASH_UNLOCK is not set
+# CONFIG_FLASH_ERASEALL is not set
+# CONFIG_IONICE is not set
+# CONFIG_INOTIFYD is not set
+# CONFIG_LAST is not set
+# CONFIG_FEATURE_LAST_SMALL is not set
+# CONFIG_FEATURE_LAST_FANCY is not set
+# CONFIG_HDPARM is not set
+# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
+# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
+# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
+CONFIG_MAKEDEVS=y
+# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
+CONFIG_FEATURE_MAKEDEVS_TABLE=y
+# CONFIG_MAN is not set
+# CONFIG_MICROCOM is not set
+# CONFIG_MOUNTPOINT is not set
+# CONFIG_MT is not set
+# CONFIG_RAIDAUTORUN is not set
+# CONFIG_READAHEAD is not set
+# CONFIG_RFKILL is not set
+# CONFIG_RUNLEVEL is not set
+# CONFIG_RX is not set
+# CONFIG_SETSID is not set
+# CONFIG_STRINGS is not set
+# CONFIG_TASKSET is not set
+# CONFIG_FEATURE_TASKSET_FANCY is not set
+CONFIG_TIME=y
+# CONFIG_TIMEOUT is not set
+# CONFIG_TTYSIZE is not set
+# CONFIG_VOLNAME is not set
+# CONFIG_WALL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Networking Utilities
+#
+# CONFIG_NAMEIF is not set
+# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
+# CONFIG_NBDCLIENT is not set
+# CONFIG_NC is not set
+# CONFIG_NC_SERVER is not set
+# CONFIG_NC_EXTRA is not set
+# CONFIG_NC_110_COMPAT is not set
+CONFIG_PING=y
+# CONFIG_PING6 is not set
+CONFIG_FEATURE_FANCY_PING=y
+# CONFIG_WHOIS is not set
+# CONFIG_FEATURE_IPV6 is not set
+# CONFIG_FEATURE_UNIX_LOCAL is not set
+# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set
+# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set
+CONFIG_ARP=y
+CONFIG_ARPING=y
+# CONFIG_BRCTL is not set
+# CONFIG_FEATURE_BRCTL_FANCY is not set
+# CONFIG_FEATURE_BRCTL_SHOW is not set
+# CONFIG_DNSD is not set
+# CONFIG_ETHER_WAKE is not set
+# CONFIG_FAKEIDENTD is not set
+# CONFIG_FTPD is not set
+# CONFIG_FEATURE_FTP_WRITE is not set
+# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set
+# CONFIG_FTPGET is not set
+# CONFIG_FTPPUT is not set
+# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
+CONFIG_HOSTNAME=y
+# CONFIG_HTTPD is not set
+# CONFIG_FEATURE_HTTPD_RANGES is not set
+# CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set
+# CONFIG_FEATURE_HTTPD_SETUID is not set
+# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set
+# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set
+# CONFIG_FEATURE_HTTPD_CGI is not set
+# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set
+# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set
+# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set
+# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set
+# CONFIG_FEATURE_HTTPD_PROXY is not set
+# CONFIG_FEATURE_HTTPD_GZIP is not set
+CONFIG_IFCONFIG=y
+CONFIG_FEATURE_IFCONFIG_STATUS=y
+CONFIG_FEATURE_IFCONFIG_SLIP=y
+CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ=y
+CONFIG_FEATURE_IFCONFIG_HW=y
+CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y
+# CONFIG_IFENSLAVE is not set
+# CONFIG_IFPLUGD is not set
+# CONFIG_IFUPDOWN is not set
+CONFIG_IFUPDOWN_IFSTATE_PATH=""
+# CONFIG_FEATURE_IFUPDOWN_IP is not set
+# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set
+# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
+# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
+# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set
+# CONFIG_INETD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
+# CONFIG_FEATURE_INETD_RPC is not set
+CONFIG_IP=y
+CONFIG_FEATURE_IP_ADDRESS=y
+CONFIG_FEATURE_IP_LINK=y
+CONFIG_FEATURE_IP_ROUTE=y
+CONFIG_FEATURE_IP_TUNNEL=y
+CONFIG_FEATURE_IP_RULE=y
+CONFIG_FEATURE_IP_SHORT_FORMS=y
+# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set
+CONFIG_IPADDR=y
+CONFIG_IPLINK=y
+CONFIG_IPROUTE=y
+CONFIG_IPTUNNEL=y
+CONFIG_IPRULE=y
+# CONFIG_IPCALC is not set
+# CONFIG_FEATURE_IPCALC_FANCY is not set
+# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
+# CONFIG_NETSTAT is not set
+# CONFIG_FEATURE_NETSTAT_WIDE is not set
+# CONFIG_FEATURE_NETSTAT_PRG is not set
+CONFIG_NSLOOKUP=y
+# CONFIG_NTPD is not set
+# CONFIG_FEATURE_NTPD_SERVER is not set
+# CONFIG_PSCAN is not set
+CONFIG_ROUTE=y
+# CONFIG_SLATTACH is not set
+# CONFIG_TCPSVD is not set
+CONFIG_TELNET=y
+CONFIG_FEATURE_TELNET_TTYPE=y
+CONFIG_FEATURE_TELNET_AUTOLOGIN=y
+CONFIG_TELNETD=y
+CONFIG_FEATURE_TELNETD_STANDALONE=y
+CONFIG_FEATURE_TELNETD_INETD_WAIT=y
+CONFIG_TFTP=y
+# CONFIG_TFTPD is not set
+
+#
+# Common options for tftp/tftpd
+#
+CONFIG_FEATURE_TFTP_GET=y
+CONFIG_FEATURE_TFTP_PUT=y
+CONFIG_FEATURE_TFTP_BLOCKSIZE=y
+CONFIG_FEATURE_TFTP_PROGRESS_BAR=y
+# CONFIG_TFTP_DEBUG is not set
+# CONFIG_TRACEROUTE is not set
+# CONFIG_TRACEROUTE6 is not set
+# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set
+# CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set
+# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set
+# CONFIG_TUNCTL is not set
+# CONFIG_FEATURE_TUNCTL_UG is not set
+# CONFIG_UDHCPC6 is not set
+# CONFIG_UDHCPD is not set
+# CONFIG_DHCPRELAY is not set
+# CONFIG_DUMPLEASES is not set
+# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set
+# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set
+CONFIG_DHCPD_LEASES_FILE=""
+# CONFIG_UDHCPC is not set
+# CONFIG_FEATURE_UDHCPC_ARPING is not set
+# CONFIG_FEATURE_UDHCP_PORT is not set
+CONFIG_UDHCP_DEBUG=0
+# CONFIG_FEATURE_UDHCP_RFC3397 is not set
+# CONFIG_FEATURE_UDHCP_8021Q is not set
+CONFIG_UDHCPC_DEFAULT_SCRIPT=""
+CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0
+CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS=""
+# CONFIG_UDPSVD is not set
+# CONFIG_VCONFIG is not set
+CONFIG_WGET=y
+CONFIG_FEATURE_WGET_STATUSBAR=y
+CONFIG_FEATURE_WGET_AUTHENTICATION=y
+CONFIG_FEATURE_WGET_LONG_OPTIONS=y
+CONFIG_FEATURE_WGET_TIMEOUT=y
+# CONFIG_ZCIP is not set
+
+#
+# Print Utilities
+#
+# CONFIG_LPD is not set
+# CONFIG_LPR is not set
+# CONFIG_LPQ is not set
+
+#
+# Mail Utilities
+#
+# CONFIG_MAKEMIME is not set
+CONFIG_FEATURE_MIME_CHARSET=""
+# CONFIG_POPMAILDIR is not set
+# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set
+# CONFIG_REFORMIME is not set
+# CONFIG_FEATURE_REFORMIME_COMPAT is not set
+# CONFIG_SENDMAIL is not set
+
+#
+# Process Utilities
+#
+CONFIG_IOSTAT=y
+CONFIG_LSOF=y
+CONFIG_MPSTAT=y
+CONFIG_NMETER=y
+CONFIG_PMAP=y
+CONFIG_POWERTOP=y
+CONFIG_PSTREE=y
+CONFIG_PWDX=y
+CONFIG_SMEMCAP=y
+CONFIG_TOP=y
+CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
+CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y
+CONFIG_FEATURE_TOP_SMP_CPU=y
+CONFIG_FEATURE_TOP_DECIMALS=y
+CONFIG_FEATURE_TOP_SMP_PROCESS=y
+CONFIG_FEATURE_TOPMEM=y
+CONFIG_UPTIME=y
+CONFIG_FEATURE_UPTIME_UTMP_SUPPORT=y
+CONFIG_FREE=y
+CONFIG_FUSER=y
+CONFIG_KILL=y
+CONFIG_KILLALL=y
+CONFIG_KILLALL5=y
+CONFIG_PGREP=y
+CONFIG_PIDOF=y
+CONFIG_FEATURE_PIDOF_SINGLE=y
+CONFIG_FEATURE_PIDOF_OMIT=y
+CONFIG_PKILL=y
+CONFIG_PS=y
+CONFIG_FEATURE_PS_WIDE=y
+CONFIG_FEATURE_PS_LONG=y
+# CONFIG_FEATURE_PS_TIME is not set
+# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set
+# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
+# CONFIG_RENICE is not set
+CONFIG_BB_SYSCTL=y
+CONFIG_FEATURE_SHOW_THREADS=y
+CONFIG_WATCH=y
+
+#
+# Runit Utilities
+#
+CONFIG_RUNSV=y
+CONFIG_RUNSVDIR=y
+CONFIG_FEATURE_RUNSVDIR_LOG=y
+CONFIG_SV=y
+CONFIG_SV_DEFAULT_SERVICE_DIR="/var/service"
+CONFIG_SVLOGD=y
+CONFIG_CHPST=y
+CONFIG_SETUIDGID=y
+CONFIG_ENVUIDGID=y
+CONFIG_ENVDIR=y
+CONFIG_SOFTLIMIT=y
+# CONFIG_CHCON is not set
+# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
+# CONFIG_GETENFORCE is not set
+# CONFIG_GETSEBOOL is not set
+# CONFIG_LOAD_POLICY is not set
+# CONFIG_MATCHPATHCON is not set
+# CONFIG_RESTORECON is not set
+# CONFIG_RUNCON is not set
+# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set
+# CONFIG_SELINUXENABLED is not set
+# CONFIG_SETENFORCE is not set
+# CONFIG_SETFILES is not set
+# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set
+# CONFIG_SETSEBOOL is not set
+# CONFIG_SESTATUS is not set
+
+#
+# Shells
+#
+CONFIG_ASH=y
+CONFIG_ASH_BASH_COMPAT=y
+# CONFIG_ASH_IDLE_TIMEOUT is not set
+CONFIG_ASH_JOB_CONTROL=y
+CONFIG_ASH_ALIAS=y
+CONFIG_ASH_GETOPTS=y
+CONFIG_ASH_BUILTIN_ECHO=y
+CONFIG_ASH_BUILTIN_PRINTF=y
+CONFIG_ASH_BUILTIN_TEST=y
+CONFIG_ASH_CMDCMD=y
+# CONFIG_ASH_MAIL is not set
+CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
+CONFIG_ASH_RANDOM_SUPPORT=y
+CONFIG_ASH_EXPAND_PRMT=y
+CONFIG_CTTYHACK=y
+CONFIG_HUSH=y
+CONFIG_HUSH_BASH_COMPAT=y
+CONFIG_HUSH_BRACE_EXPANSION=y
+CONFIG_HUSH_HELP=y
+CONFIG_HUSH_INTERACTIVE=y
+# CONFIG_HUSH_SAVEHISTORY is not set
+CONFIG_HUSH_JOB=y
+CONFIG_HUSH_TICK=y
+CONFIG_HUSH_IF=y
+CONFIG_HUSH_LOOPS=y
+CONFIG_HUSH_CASE=y
+CONFIG_HUSH_FUNCTIONS=y
+CONFIG_HUSH_LOCAL=y
+CONFIG_HUSH_RANDOM_SUPPORT=y
+CONFIG_HUSH_EXPORT_N=y
+CONFIG_HUSH_MODE_X=y
+CONFIG_MSH=y
+# CONFIG_FEATURE_SH_IS_ASH is not set
+CONFIG_FEATURE_SH_IS_HUSH=y
+# CONFIG_FEATURE_SH_IS_NONE is not set
+# CONFIG_FEATURE_BASH_IS_ASH is not set
+# CONFIG_FEATURE_BASH_IS_HUSH is not set
+CONFIG_FEATURE_BASH_IS_NONE=y
+CONFIG_SH_MATH_SUPPORT=y
+CONFIG_SH_MATH_SUPPORT_64=y
+CONFIG_FEATURE_SH_EXTRA_QUIET=y
+CONFIG_FEATURE_SH_STANDALONE=y
+CONFIG_FEATURE_SH_NOFORK=y
+CONFIG_FEATURE_SH_HISTFILESIZE=y
+
+#
+# System Logging Utilities
+#
+CONFIG_SYSLOGD=y
+CONFIG_FEATURE_ROTATE_LOGFILE=y
+CONFIG_FEATURE_REMOTE_LOG=y
+CONFIG_FEATURE_SYSLOGD_DUP=y
+CONFIG_FEATURE_SYSLOGD_CFG=y
+CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=256
+CONFIG_FEATURE_IPC_SYSLOG=y
+CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16
+CONFIG_LOGREAD=y
+CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING=y
+CONFIG_FEATURE_KMSG_SYSLOG=y
+CONFIG_KLOGD=y
+
+#
+# klogd should not be used together with syslog to kernel printk buffer
+#
+CONFIG_FEATURE_KLOGD_KLOGCTL=y
+CONFIG_LOGGER=y
diff --git a/tests/arm64/common/busybox/busybox_dev.txt b/tests/arm64/common/busybox/busybox_dev.txt
new file mode 100644
index 0000000..91c0b6a
--- /dev/null
+++ b/tests/arm64/common/busybox/busybox_dev.txt
@@ -0,0 +1,70 @@
+# name type mode uid gid major minor start inc count
+/dev d 755 0 0 - - - - -
+/dev/pts d 755 0 0 - - - - -
+/dev/initctl p 400 0 0 0 0 0 0 -
+/dev/console c 620 0 0 5 1 0 0 -
+/dev/fb0 c 600 0 0 29 0 0 0 -
+/dev/flasha c 755 0 0 60 0 0 0 -
+/dev/flasha c 755 0 0 60 1 1 1 8
+/dev/flashb c 755 0 0 60 8 0 0 -
+/dev/flashb c 755 0 0 60 9 1 1 8
+/dev/full c 666 0 0 1 7 0 0 -
+/dev/hda b 660 0 0 3 0 0 0 -
+/dev/hda b 660 0 0 3 1 1 1 16
+/dev/hdb b 660 0 0 3 64 0 0 -
+/dev/hdb b 660 0 0 3 65 1 1 16
+/dev/hvc c 620 0 0 229 0 0 1 4
+/dev/sda b 660 0 0 8 0 0 0 -
+/dev/sda b 660 0 0 8 1 1 1 16
+/dev/sdb b 660 0 0 8 16 0 0 -
+/dev/sdb b 660 0 0 8 17 1 1 16
+/dev/sdc b 660 0 0 8 32 0 0 -
+/dev/sdc b 660 0 0 8 33 1 1 16
+/dev/kmem c 640 0 0 1 2 0 0 -
+/dev/mem c 640 0 0 1 1 0 0 -
+/dev/mtd c 664 0 0 90 0 0 2 17
+/dev/mtdblock b 664 0 0 31 0 0 1 17
+/dev/mtdchar c 755 0 0 90 0 0 1 8
+/dev/mtdr0 c 664 0 0 90 1 0 1 17
+/dev/mmcblk0 b 664 0 0 179 0 0 0 -
+/dev/mmcblk0p b 664 0 0 179 1 1 1 8
+/dev/mmcblk1 b 664 0 0 179 8 0 0 -
+/dev/mmcblk1p b 664 0 0 179 9 1 1 8
+/dev/nftla b 755 0 0 93 0 0 0 -
+/dev/nftla1 b 755 0 0 93 1 1 1 16
+/dev/nftlb b 755 0 0 93 16 0 0 -
+/dev/nftlb1 b 755 0 0 93 17 1 1 16
+/dev/null c 666 0 0 1 3 0 0 -
+/dev/psaux c 600 0 0 10 1 0 0 -
+/dev/ptmx c 666 0 0 5 2 0 0 -
+/dev/ptyp c 666 0 0 2 0 0 1 10
+/dev/ptypa c 666 0 0 2 10 0 0 -
+/dev/ptypb c 666 0 0 2 11 0 0 -
+/dev/ptypc c 666 0 0 2 12 0 0 -
+/dev/ptypd c 666 0 0 2 13 0 0 -
+/dev/ptype c 666 0 0 2 14 0 0 -
+/dev/ptypf c 666 0 0 2 15 0 0 -
+/dev/ram b 640 0 0 1 1 0 0 -
+/dev/ram0 b 660 0 0 1 0 0 0 -
+/dev/ram1 b 660 0 0 1 1 0 0 -
+/dev/rtc c 644 0 0 10 135 0 0 -
+/dev/tty c 666 0 0 5 0 0 0 -
+/dev/tty c 620 0 0 4 0 0 1 10
+/dev/ttyCPM c 620 0 0 204 46 0 1 6
+/dev/ttyAMA c 620 0 0 204 64 0 1 4
+/dev/ttyp c 620 0 0 3 0 0 1 10
+/dev/ttypa c 620 0 0 3 10 0 0 -
+/dev/ttypb c 620 0 0 3 11 0 0 -
+/dev/ttypc c 620 0 0 3 12 0 0 -
+/dev/ttypd c 620 0 0 3 13 0 0 -
+/dev/ttype c 620 0 0 3 14 0 0 -
+/dev/ttypf c 620 0 0 3 15 0 0 -
+/dev/ttyS c 660 0 0 4 64 0 1 8
+/dev/vda b 660 0 0 254 0 0 0 -
+/dev/vda b 660 0 0 254 1 1 1 16
+/dev/vdb b 660 0 0 254 16 0 0 -
+/dev/vdb b 660 0 0 254 17 1 1 16
+/dev/watchdog c 666 0 0 10 130 0 0 -
+/dev/zero c 666 0 0 1 5 0 0 -
+/dev/random c 644 0 0 1 8 0 0 -
+/dev/urandom c 644 0 0 1 9 0 0 -
diff --git a/tests/arm64/virt-v8/README b/tests/arm64/virt-v8/README
new file mode 100644
index 0000000..bade6a3
--- /dev/null
+++ b/tests/arm64/virt-v8/README
@@ -0,0 +1,29 @@
+ Virt-v8 Guest
+
+The Virt-v8 is a fully para-virtualized guest with ARMv8 CPUs.
+
+We only have memory mapped VirtIO devices for IO and this makes the
+Guest as fully para-virtualized.
+
+The memory map and irqs in Virt-v8 guest is as follows:
+0x0000000000000000-0x0000000000FFFFFF (16M) (NOR Flash)
+0x000000002C001000–0x000000002C001FFF (4K) (GIC Distributor Interface)
+0x000000002C002000–0x000000002C002FFF (4K) (GIC CPU Interface)
+0x0000000040200000–0x0000000040200FFF (4K) (IRQ=40) (VirtIO Network Device)
+0x0000000040400000–0x0000000040400FFF (4K) (IRQ=41) (VirtIO Block Device)
+0x0000000040600000–0x0000000040600FFF (4K) (IRQ=42) (VirtIO Console Device)
+0x0000000080000000-0xFFFFFFFFFFFFFFFF (---) (RAM)
+
+In addition, we also have ARMv8 generic timer accessible to all VCPUs
+of the Guest with virtual timer irq 27 and physical timer irq 30.
+
+
+ Virt-v8 Guest OSes
+
+We have tested following guest OSes for this guest:
+
+ 1. basic - Basic firmware/bootloader
+ 2. linux - Linux Kernel
+
+Please follow the README under specific guest OS directory for detailed
+steps to configure, compile and run.
diff --git a/tests/arm64/virt-v8/basic/Makefile b/tests/arm64/virt-v8/basic/Makefile
new file mode 100644
index 0000000..3db2006
--- /dev/null
+++ b/tests/arm64/virt-v8/basic/Makefile
@@ -0,0 +1,43 @@
+#/**
+# Copyright (c) 2013 Sukanto Ghosh.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# @file Makefile
+# @brief toplevel makefile to build ARM test code
+# */
+
+# Determine the build directory
+top_dir=$(CURDIR)/../../../..
+ifdef O
+ build_dir=$(shell readlink -f $(O))
+else
+ build_dir=$(top_dir)/build
+endif
+
+obj_dir=$(build_dir)/tests/arm64/virt-v8/basic
+common_dir=$(top_dir)/tests/arm64/common/basic
+
+board_text_start = 0x81000000
+board_objs = $(obj_dir)/arm_board.o \
+ $(obj_dir)/pic/gic.o \
+ $(obj_dir)/timer/generic_timer.o \
+ $(obj_dir)/serial/virtio_console.o
+
+# Include common makefile for basic test
+include $(common_dir)/Makefile.inc
+
diff --git a/tests/arm64/virt-v8/basic/README b/tests/arm64/virt-v8/basic/README
new file mode 100644
index 0000000..0ca69263
--- /dev/null
+++ b/tests/arm64/virt-v8/basic/README
@@ -0,0 +1,61 @@
+ Basic Firmware on Virt-v8 Guest
+
+The basic firmware currently sets up PIC, Timer, and UART and emulates
+a dummy terminal which reponds to various commands. It also includes an
+extensive MMU test suite and dhrystone benchmark.
+
+Hardware features tested by Basic Firmware:
+ - Crucial EL1 instructions
+ - Virtual IRQs
+ - Generic Interrupt Controller (GIC)
+ - ARMv8 Generic Timers
+ - VirtIO console emergency write
+
+Please follow the steps below to build & run Basic Firmware on Virt-v8
+Guest with Xvisor running on Foundation v8 Model:
+
+ [1. Build environment for Xvisor]
+ # CROSS_COMPILE=aarch64-none-linux-gnu-
+
+ [2. GoTo Xvisor source directory]
+ # cd <xvisor_source_directory>
+
+ [3. Configure Xvisor with Generic-v8 default settings]
+ # make ARCH=arm generic-v8-defconfig
+
+ [4. Build Xvisor]
+ # make
+
+ [5. Build Xvisor DTBs for Generic-v8]
+ # make dtbs
+
+ [6. Build Basic Firmware]
+ # make -C tests/arm64/virt-v8/basic
+
+ [7. Create foundation_v8_boot.axf for running it on Foundation v8 Model]
+ # ./tools/scripts/memimg.py -a 0x80010000 -o ./build/foundation_v8_boot.img ./build/vmm.bin@0x80010000 ./build/tests/arm64/virt-v8/basic/firmware.bin@0x81000000
+ # ${CROSS_COMPILE}gcc -nostdlib -nostdinc -e _start -Wl,-Ttext=0x80000000 -DGENTIMER_FREQ=100000000 -DGIC_DIST_BASE=0x2c001000 -DGIC_CPU_BASE=0x2c002000 -DSPIN_LOOP_ADDR=0x84000000 -DIMAGE=./build/foundation_v8_boot.img -DDTB=./build/arch/arm/board/generic-v8/dts/foundation-v8/one_guest_virt_v8.dtb ./docs/arm/foundation_v8_boot.S -o ./build/foundation_v8_boot.axf
+
+ [8. Launch Foundation v8 Model]
+ # <foundation_v8_install_directory>/models/Linux64_GCC-4.1/Foundation_v8 --image ./build/foundation_v8_boot.axf --network=nat
+
+ [9. Kick Guest0 for starting Basic Firmware]
+ XVisor# guest kick guest0
+
+ [10. Bind to VirtIO Console]
+ XVisor# vserial bind guest0/virtio-con0
+
+ [11. Say 'hi' to Basic Firmware]
+ [guest0/uart0] basic# hi
+
+ [12. Say 'hello' to Basic Firmware]
+ [guest0/uart0] basic# hello
+
+ [13. Check various commands of Basic Firmware]
+ [guest0/uart0] basic# help
+
+ [14. Enter character seqence 'ESCAPE+x+q" return to Xvisor prompt]
+ [guest0/uart0] basic#
+
+ (Note: replace all <> brackets based on your workspace)
+
diff --git a/tests/arm64/virt-v8/basic/arm_board.c b/tests/arm64/virt-v8/basic/arm_board.c
new file mode 100644
index 0000000..db981df
--- /dev/null
+++ b/tests/arm64/virt-v8/basic/arm_board.c
@@ -0,0 +1,214 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_board.c
+ * @brief various platform specific functions
+ */
+
+#include <arm_types.h>
+#include <arm_string.h>
+#include <arm_board.h>
+#include <arm_plat.h>
+#include <pic/gic.h>
+#include <timer/generic_timer.h>
+#include <serial/virtio_console.h>
+
+void arm_board_reset(void)
+{
+ /* Nothing to do */
+}
+
+void arm_board_init(void)
+{
+ /* Nothing to do */
+}
+
+char *arm_board_name(void)
+{
+ return "Virt-v8";
+}
+
+physical_addr_t arm_board_ram_start(void)
+{
+ return VIRT_V8_RAM0;
+}
+
+physical_size_t arm_board_ram_size(void)
+{
+ return VIRT_V8_RAM0_SIZE;
+}
+
+void arm_board_linux_default_cmdline(char *cmdline, u32 cmdline_sz)
+{
+ arm_strcpy(cmdline, "root=/dev/ram rw "
+ "earlyprintk=virtio-console,0x40600000 "
+ "console=hvc0");
+}
+
+physical_addr_t arm_board_flash_addr(void)
+{
+ return VIRT_V8_NOR_FLASH_0;
+}
+
+u32 arm_board_iosection_count(void)
+{
+ return 5;
+}
+
+physical_addr_t arm_board_iosection_addr(int num)
+{
+ physical_addr_t ret = 0;
+
+ switch (num) {
+ case 0:
+ /* nor-flash */
+ ret = VIRT_V8_NOR_FLASH_0;
+ break;
+ case 1:
+ /* gic */
+ ret = VIRT_V8_GIC;
+ break;
+ case 2:
+ /* virtio-net */
+ ret = VIRT_V8_VIRTIO_NET;
+ break;
+ case 3:
+ /* virtio-blk */
+ ret = VIRT_V8_VIRTIO_BLK;
+ break;
+ case 4:
+ /* virtio-con */
+ ret = VIRT_V8_VIRTIO_CON;
+ break;
+ default:
+ while (1);
+ break;
+ }
+
+ return ret;
+}
+
+u32 arm_board_pic_nr_irqs(void)
+{
+ return NR_IRQS_VIRT_V8;
+}
+
+int arm_board_pic_init(void)
+{
+ int rc;
+
+ /*
+ * Initialize Generic Interrupt Controller
+ */
+ rc = gic_dist_init(0, VIRT_V8_GIC_DIST, IRQ_VIRT_V8_GIC_START);
+ if (rc) {
+ return rc;
+ }
+ rc = gic_cpu_init(0, VIRT_V8_GIC_CPU);
+ if (rc) {
+ return rc;
+ }
+
+ return 0;
+}
+
+u32 arm_board_pic_active_irq(void)
+{
+ return gic_active_irq(0);
+}
+
+int arm_board_pic_ack_irq(u32 irq)
+{
+ return 0;
+}
+
+int arm_board_pic_eoi_irq(u32 irq)
+{
+ return gic_eoi_irq(0, irq);
+}
+
+int arm_board_pic_mask(u32 irq)
+{
+ return gic_mask(0, irq);
+}
+
+int arm_board_pic_unmask(u32 irq)
+{
+ return gic_unmask(0, irq);
+}
+
+void arm_board_timer_enable(void)
+{
+ return generic_timer_enable();
+}
+
+void arm_board_timer_disable(void)
+{
+ return generic_timer_disable();
+}
+
+u64 arm_board_timer_irqcount(void)
+{
+ return generic_timer_irqcount();
+}
+
+u64 arm_board_timer_irqdelay(void)
+{
+ return generic_timer_irqdelay();
+}
+
+u64 arm_board_timer_timestamp(void)
+{
+ return generic_timer_timestamp();
+}
+
+void arm_board_timer_change_period(u32 usecs)
+{
+ return generic_timer_change_period(usecs);
+}
+
+int arm_board_timer_init(u32 usecs)
+{
+ return generic_timer_init(usecs, IRQ_VIRT_V8_VIRT_TIMER);
+}
+
+int arm_board_serial_init(void)
+{
+ return virtio_console_init(VIRT_V8_VIRTIO_CON);
+}
+
+void arm_board_serial_putc(char ch)
+{
+ if (ch == '\n') {
+ virtio_console_printch(VIRT_V8_VIRTIO_CON, '\r');
+ }
+ virtio_console_printch(VIRT_V8_VIRTIO_CON, ch);
+}
+
+char arm_board_serial_getc(void)
+{
+ char ch = virtio_console_getch(VIRT_V8_VIRTIO_CON);
+ if (ch == '\r') {
+ ch = '\n';
+ }
+ virtio_console_printch(VIRT_V8_VIRTIO_CON, ch);
+ return ch;
+}
+
+
diff --git a/tests/arm64/virt-v8/basic/arm_plat.h b/tests/arm64/virt-v8/basic/arm_plat.h
new file mode 100644
index 0000000..76dfd98
--- /dev/null
+++ b/tests/arm64/virt-v8/basic/arm_plat.h
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file arm_plat.h
+ * @brief Platform Configuration for virt-v8 board
+ */
+#ifndef __ARM_PLAT_H__
+#define __ARM_PLAT_H__
+
+#define VIRT_V8_NOR_FLASH_0 (0x000000000)
+#define VIRT_V8_NOR_FLASH_0_SIZE (0x001000000)
+#define VIRT_V8_GIC (0x02c000000)
+#define VIRT_V8_GIC_SIZE (0x000003000)
+#define VIRT_V8_VIRTIO_NET (0x040200000)
+#define VIRT_V8_VIRTIO_NET_SIZE (0x000001000)
+#define VIRT_V8_VIRTIO_BLK (0x040400000)
+#define VIRT_V8_VIRTIO_BLK_SIZE (0x000001000)
+#define VIRT_V8_VIRTIO_CON (0x040600000)
+#define VIRT_V8_VIRTIO_CON_SIZE (0x000001000)
+#define VIRT_V8_RAM0 (0x080000000)
+#define VIRT_V8_RAM0_SIZE (0x006000000)
+
+#define VIRT_V8_GIC_DIST (VIRT_V8_GIC + 0x1000)
+#define VIRT_V8_GIC_CPU (VIRT_V8_GIC + 0x2000)
+
+/*
+ * Interrupts.
+ */
+#define IRQ_VIRT_V8_VIRT_TIMER 27
+#define IRQ_VIRT_V8_PHYS_TIMER 30
+
+#define IRQ_VIRT_V8_VIRTIO_NET 40
+#define IRQ_VIRT_V8_VIRTIO_BLK 41
+#define IRQ_VIRT_V8_VIRTIO_CON 42
+
+#define IRQ_VIRT_V8_GIC_START 16
+#define NR_IRQS_VIRT_V8 128
+#define NR_GIC_VIRT_V8 1
+
+#define IRQ_VIRT_TIMER IRQ_VIRT_V8_VIRT_TIMER
+
+/*
+ * Defines required by common code
+ */
+#define ARM_PLAT_SPIN_ADDR 0x80000100
+
+#endif
diff --git a/tests/arm64/virt-v8/basic/gic_config.h b/tests/arm64/virt-v8/basic/gic_config.h
new file mode 100644
index 0000000..8f95c27
--- /dev/null
+++ b/tests/arm64/virt-v8/basic/gic_config.h
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2013 Sukanto Ghosh.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file gic_config.h
+ * @brief ARM Generic Interrupt Controller configuration header
+ */
+#ifndef _GIC_CONFIG_H__
+#define _GIC_CONFIG_H__
+
+#include <arm_plat.h>
+
+#define GIC_CPU_BASE VIRT_V8_GIC_CPU
+#define GIC_DIST_BASE VIRT_V8_GIC_DIST
+
+#if !defined(GIC_NR_IRQS) || (GIC_NR_IRQS < NR_IRQS_CA15X4)
+#undef GIC_NR_IRQS
+#define GIC_NR_IRQS NR_IRQS_VIRT_V8
+#endif
+
+#if !defined(GIC_MAX_NR) || (GIC_MAX_NR < NR_GIC_CA15X4)
+#undef GIC_MAX_NR
+#define GIC_MAX_NR NR_GIC_VIRT_V8
+#endif
+
+#endif
diff --git a/tests/arm64/virt-v8/linux/README b/tests/arm64/virt-v8/linux/README
new file mode 100644
index 0000000..a7091ff
--- /dev/null
+++ b/tests/arm64/virt-v8/linux/README
@@ -0,0 +1,95 @@
+ Linux on Xvisor Virt-v8 SMP Guest
+
+Linux is a computer operating system which is based on free and open source
+software. the underlying source code can be used, freely modified, and
+redistributed, both commercially and non-commercially, by anyone under
+licenses such as the GNU General Public License. For more information on
+Linux read the wiki page
http://en.wikipedia.org/wiki/Linux
+
+Linux already contains a support for device-tree based boards. We can use
+this kernel unmodified to run it as a xvisor guest. We have also provide
+a defconfig for building kernel. To obtain Linux kernel sources visit the
+following url:
http://www.kernel.org
+
+Please follow the steps below to build & run Linux kernel with Busybox
+RootFS on Virt-v8 (paravirtualized ARMv8) Guest with Xvisor running on
+Foundation v8 model:
+
+ [1. Build environment for Xvisor]
+ # CROSS_COMPILE=aarch64-linux-gnu-
+
+ [2. GoTo Xvisor source directory]
+ # cd <xvisor_source_directory>
+
+ [3. Configure Xvisor with Generic-V8 default settings]
+ # make ARCH=arm generic-v8-defconfig
+
+ [4. Build Xvisor]
+ # make
+
+ [5. Build DTBs]
+ # make dtbs
+
+ [6. Build Basic Firmware]
+ # make -C tests/arm64/virt-v8/basic
+
+ [7. Copy Linux defconfig to Linux build directory]
+ # cp tests/arm64/virt-v8/linux/linux-<linux_version>_virt_v8_defconfig <linux_build_directory>/.config
+
+ [8. GoTo Linux source directory]
+ # cd <linux_source_directory>
+
+ [9. Apply patch for virtio-console earlyprintk support]
+ # patch -p1 < <xvisor_source_directory>/tests/arm64/virt-v8/linux/linux-3.11-virtio-console-earlyprintk.patch
+ (Note: This is an optional but recommended step. Without this earlyprintks will not work on virtio-console)
+
+ [10. Configure Linux in build directory]
+ # make O=<linux_build_directory> ARCH=arm64 oldconfig
+
+ [11. Build Linux in build directory to reflect changes in kernel image]
+ # make O=<linux_build_directory> ARCH=arm64 Image
+
+ [12. Create BusyBox RAMDISK to be used as RootFS for Linux kernel]
+ (Note: For subsequent steps, we will assume that your RAMDISK is located at <busybox_rootfs_directory>/rootfs64.img)
+ (Note: Please refer tests/arm64/common/busybox/README for creating rootfs64.img using BusyBox)
+
+ [13. GoTo Linux build directory]
+ # cd <linux_build_directory>
+
+ [14. Build virt-v8.dtb for guest linux]
+ # ./scripts/dtc/dtc -I dts -O dtb -p 0x800 -o virt-v8.dtb <xvisor_source_directory>/tests/arm64/virt-v8/linux/virt-v8.dts
+
+ [15. Create foundation_v8_boot.axf for running it on Foundation v8 model]
+ # <xvisor_source_directory>/tools/scripts/memimg.py -a 0x80010000 -o foundation_v8_boot.img <xvisor_source_directory>/build/vmm.bin@0x80010000 <xvisor_source_directory>/build/tests/arm64/virt-v8/basic/firmware.bin@0x81000000 <xvisor_source_directory>/tests/arm64/virt-v8/linux/cmdlist@0x810FF000 <linux_build_directory>/arch/arm64/boot/Image@0x81100000 <linux_build_directory>/virt-v8.dtb@0x81600000 <busybox_rootfs_directory>/rootfs64.img@0x81700000
+ # ${CROSS_COMPILE}gcc -nostdlib -nostdinc -e _start -Wl,-Ttext=0x80000000 -DGENTIMER_FREQ=100000000 -DGIC_DIST_BASE=0x2c001000 -DGIC_CPU_BASE=0x2c002000 -DSPIN_LOOP_ADDR=0x84000000 -DIMAGE=foundation_v8_boot.img -DDTB=<xvisor_source_directory>/build/arch/arm/board/generic-v8/dts/foundation-v8/one_guest_virt_v8.dtb <xvisor_source_directory>/docs/arm/foundation_v8_boot.S -o foundation_v8_boot.axf
+
+ [16. Launch Foundation v8 Model]
+ # <foundation_v8_install_directory>/models/Linux64_GCC-4.1/Foundation_v8 --image foundation_v8_boot.axf --network=nat
+
+ [17. Kick Guest0 to start Basic Firmware]
+ XVisor# guest kick guest0
+
+ [18. Bind to VirtIO Console]
+ XVisor# vserial bind guest0/virtio-con0
+
+ [19. Copy linux from NOR flash to RAM and start linux booting from RAM]
+ [guest0/virtio-con0] basic# copy 0x80080000 0x00100000 0x500000
+ (Note: This command will copy Image to RAM)
+ [guest0/virtio-con0] basic# copy 0x80F00000 0x00600000 0x004000
+ (Note: This command will copy virt-v8.dtb to RAM)
+ [guest0/virtio-con0] basic# copy 0x82000000 0x00700000 0x600000
+ (Note: This command will copy rootfs64.img to RAM)
+ [guest0/virtio-con0] basic# start_linux 0x80080000 0x82000000 0x600000 0x80F00000
+ (Note: This command will start linux booting)
+ OR
+ [guest0/virtio-con0] basic# autoexec
+ (Note: "autoexec" is a short-cut command)
+
+ [20. Wait for Linux prompt to come-up and then try out some commands]
+ [guest0/virtio-con0] / # ls
+
+ [21. Enter character seqence 'ESCAPE+x+q" return to Xvisor prompt]
+ [guest0/virtio-con0] / #
+
+ (Note: replace all <> brackets based on your workspace)
+
diff --git a/tests/arm64/virt-v8/linux/cmdlist b/tests/arm64/virt-v8/linux/cmdlist
new file mode 100644
index 0000000..a7cbefb
--- /dev/null
+++ b/tests/arm64/virt-v8/linux/cmdlist
@@ -0,0 +1,5 @@
+copy 0x80080000 0x00100000 0x500000
+copy 0x80F00000 0x00600000 0x004000
+copy 0x82000000 0x00700000 0x600000
+start_linux 0x80080000 0x82000000 0x600000 0x80F00000
+
diff --git a/tests/arm64/virt-v8/linux/linux-3.11-virtio-console-earlyprintk.patch b/tests/arm64/virt-v8/linux/linux-3.11-virtio-console-earlyprintk.patch
new file mode 100644
index 0000000..6886110
--- /dev/null
+++ b/tests/arm64/virt-v8/linux/linux-3.11-virtio-console-earlyprintk.patch
@@ -0,0 +1,61 @@
+diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c
+index fbb6e18..7ac8efd 100644
+--- a/arch/arm64/kernel/early_printk.c
++++ b/arch/arm64/kernel/early_printk.c
+@@ -25,6 +25,9 @@
+
+ #include <linux/amba/serial.h>
+ #include <linux/serial_reg.h>
++#include <linux/virtio_ids.h>
++#include <linux/virtio_mmio.h>
++#include <linux/virtio_console.h>
+
+ static void __iomem *early_base;
+ static void (*printch)(char ch);
+@@ -53,6 +56,37 @@ static void smh_printch(char ch)
+ }
+
+ /*
++ * VIRTIO MMIO console single character Tx.
++ */
++static void virtio_console_printch(char ch)
++{
++ u32 tmp;
++ static u32 init_done;
++ static u32 can_write;
++ struct virtio_console_config *p = early_base + VIRTIO_MMIO_CONFIG;
++
++ if (!init_done) {
++ tmp = readl_relaxed(early_base + VIRTIO_MMIO_DEVICE_ID);
++ if (tmp != VIRTIO_ID_CONSOLE) {
++ init_done = 1;
++ return;
++ }
++
++ tmp = readl_relaxed(early_base + VIRTIO_MMIO_HOST_FEATURES);
++ if (!(tmp & (1 << VIRTIO_CONSOLE_F_EMERG_WRITE))) {
++ init_done = 1;
++ return;
++ }
++
++ init_done = 1;
++ can_write = 1;
++ }
++
++ if (can_write)
++ writeb_relaxed(ch, &p->emerg_wr);
++}
++
++/*
+ * 8250/16550 (8-bit aligned registers) single character TX.
+ */
+ static void uart8250_8bit_printch(char ch)
+@@ -82,6 +116,7 @@ static const struct earlycon_match earlycon_match[] __initconst = {
+ { .name = "smh", .printch = smh_printch, },
+ { .name = "uart8250-8bit", .printch = uart8250_8bit_printch, },
+ { .name = "uart8250-32bit", .printch = uart8250_32bit_printch, },
++ { .name = "virtio-console", .printch = virtio_console_printch, },
+ {}
+ };
+
+
diff --git a/tests/arm64/virt-v8/linux/linux-3.11_virt_v8_defconfig b/tests/arm64/virt-v8/linux/linux-3.11_virt_v8_defconfig
new file mode 100644
index 0000000..96348a1
--- /dev/null
+++ b/tests/arm64/virt-v8/linux/linux-3.11_virt_v8_defconfig
@@ -0,0 +1,1399 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm64 3.11.0-rc7 Kernel Configuration
+#
+CONFIG_ARM64=y
+CONFIG_64BIT=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_MMU=y
+CONFIG_NO_IOPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA32=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_SPARSE_IRQ=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RCU_FANOUT=64
+CONFIG_RCU_FANOUT_LEAF=16
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_NOCB_CPU is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
+# CONFIG_CGROUP_PERF is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_CFS_BANDWIDTH is not set
+# CONFIG_RT_GROUP_SCHED is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_UIDGID_CONVERTED=y
+# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_RD_LZ4=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+CONFIG_SLUB_CPU_PARTIAL=y
+CONFIG_PROFILING=y
+CONFIG_HAVE_64BIT_ALIGNED_ACCESS=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_COMPAT_OLD_SIGACTION=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+# CONFIG_FREEZER is not set
+
+#
+# Platform selection
+#
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_XGENE=y
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Kernel Features
+#
+# CONFIG_ARM64_64K_PAGES is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HW_PERF_EVENTS=y
+CONFIG_SYS_SUPPORTS_HUGETLBFS=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_ZBUD is not set
+# CONFIG_XEN is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+
+#
+# Boot options
+#
+CONFIG_CMDLINE="console=ttyAMA0"
+# CONFIG_CMDLINE_FORCE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_NET_MPLS_GSO is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+# CONFIG_NETPRIO_CGROUP is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+CONFIG_NET_FLOW_LIMIT=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+# CONFIG_DEVTMPFS_MOUNT is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+CONFIG_FW_LOADER_USER_HELPER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+
+#
+# Device Tree and Open Firmware support
+#
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_OF_SELFTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=10240
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_VIRTIO_BLK=y
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_ATMEL_PWM is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ATMEL_SSC is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+
+#
+# Altera FPGA firmware download module
+#
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_VIRTIO_NET=y
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_ARC=y
+# CONFIG_ARC_EMAC is not set
+CONFIG_NET_CADENCE=y
+# CONFIG_ARM_AT91_ETHER is not set
+# CONFIG_MACB is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_INTEL=y
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_MVMDIO is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8851_MLL is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_ETHOC is not set
+# CONFIG_SH_ETH is not set
+CONFIG_NET_VENDOR_SEEQ=y
+CONFIG_NET_VENDOR_SMSC=y
+CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_VIA=y
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_SERIO_OLPC_APSP is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_DW is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+CONFIG_HVC_DRIVER=y
+CONFIG_VIRTIO_CONSOLE=y
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_TS5500 is not set
+# CONFIG_GPIO_GRGPIO is not set
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+
+#
+# USB GPIO expanders:
+#
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_BATTERY_GOLDFISH is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_GPIO is not set
+CONFIG_POWER_RESET_VEXPRESS=y
+# CONFIG_POWER_AVS is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_TPS65912 is not set
+# CONFIG_MFD_TMIO is not set
+CONFIG_VEXPRESS_CONFIG=y
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_GOLDFISH is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_EXYNOS_VIDEO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=y
+# CONFIG_HID_AUREAL is not set
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+CONFIG_HID_KENSINGTON=y
+# CONFIG_HID_LCPOWER is not set
+CONFIG_HID_LOGITECH=y
+# CONFIG_HID_LOGITECH_DJ is not set
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+CONFIG_VIRT_DRIVERS=y
+CONFIG_VIRTIO=y
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_BALLOON is not set
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_DEBUG is not set
+CONFIG_COMMON_CLK_VERSATILE=y
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_ARM_ARCH_TIMER=y
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_VIRTUALIZATION is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_HAVE_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=21
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+CONFIG_ATOMIC64_SELFTEST=y
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_PID_IN_CONTEXTIDR is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=m
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_USER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_PCRYPT is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IO=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_ARM is not set
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_SPARC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_FONT_SUPPORT=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
diff --git a/tests/arm64/virt-v8/linux/virt-v8.dts b/tests/arm64/virt-v8/linux/virt-v8.dts
new file mode 100644
index 0000000..d2158fb
--- /dev/null
+++ b/tests/arm64/virt-v8/linux/virt-v8.dts
@@ -0,0 +1,153 @@
+
+/dts-v1/;
+
+/ {
+ model = "Virt-v8";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ chosen { };
+
+ aliases { };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x0>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x8000fff8>;
+ };
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x1>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x8000fff8>;
+ };
+ cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x2>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x8000fff8>;
+ };
+ cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x3>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x8000fff8>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x00000000 0x80000000 0 0x06000000>;
+ };
+
+ gic: interrupt-controller@2c001000 {
+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x0 0x2c001000 0 0x1000>,
+ <0x0 0x2c002000 0 0x1000>,
+ <0x0 0x2c004000 0 0x2000>,
+ <0x0 0x2c006000 0 0x2000>;
+ interrupts = <1 9 0xf04>;
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <1 13 0xff01>,
+ <1 14 0xff01>,
+ <1 11 0xff01>,
+ <1 10 0xff01>;
+ clock-frequency = <100000000>;
+ };
+
+ pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <0 60 4>,
+ <0 61 4>,
+ <0 62 4>,
+ <0 63 4>;
+ };
+
+ smb {
+ compatible = "simple-bus";
+ #address-cells = <2>; /* SMB chipselect number and offset */
+ #size-cells = <1>;
+
+ ranges = <0 0 0 0x40000000 0x04000000>;
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 63>;
+ interrupt-map = <0 0 0 &gic 0 0 4>,
+ <0 0 1 &gic 0 1 4>,
+ <0 0 2 &gic 0 2 4>,
+ <0 0 3 &gic 0 3 4>,
+ <0 0 4 &gic 0 4 4>,
+ <0 0 5 &gic 0 5 4>,
+ <0 0 6 &gic 0 6 4>,
+ <0 0 7 &gic 0 7 4>,
+ <0 0 8 &gic 0 8 4>,
+ <0 0 9 &gic 0 9 4>,
+ <0 0 10 &gic 0 10 4>,
+ <0 0 11 &gic 0 11 4>,
+ <0 0 12 &gic 0 12 4>,
+ <0 0 13 &gic 0 13 4>,
+ <0 0 14 &gic 0 14 4>,
+ <0 0 15 &gic 0 15 4>,
+ <0 0 16 &gic 0 16 4>,
+ <0 0 17 &gic 0 17 4>,
+ <0 0 18 &gic 0 18 4>,
+ <0 0 19 &gic 0 19 4>,
+ <0 0 20 &gic 0 20 4>,
+ <0 0 21 &gic 0 21 4>,
+ <0 0 22 &gic 0 22 4>,
+ <0 0 23 &gic 0 23 4>,
+ <0 0 24 &gic 0 24 4>,
+ <0 0 25 &gic 0 25 4>,
+ <0 0 26 &gic 0 26 4>,
+ <0 0 27 &gic 0 27 4>,
+ <0 0 28 &gic 0 28 4>,
+ <0 0 29 &gic 0 29 4>,
+ <0 0 30 &gic 0 30 4>,
+ <0 0 31 &gic 0 31 4>,
+ <0 0 32 &gic 0 32 4>,
+ <0 0 33 &gic 0 33 4>,
+ <0 0 34 &gic 0 34 4>,
+ <0 0 35 &gic 0 35 4>,
+ <0 0 36 &gic 0 36 4>,
+ <0 0 37 &gic 0 37 4>,
+ <0 0 38 &gic 0 38 4>,
+ <0 0 39 &gic 0 39 4>,
+ <0 0 40 &gic 0 40 4>,
+ <0 0 41 &gic 0 41 4>,
+ <0 0 42 &gic 0 42 4>;
+
+ virtio_net@0200000 {
+ compatible = "virtio,mmio";
+ reg = <0 0x00200000 0x10000>;
+ interrupts = <8>;
+ };
+
+ virtio_block@0400000 {
+ compatible = "virtio,mmio";
+ reg = <0 0x00400000 0x10000>;
+ interrupts = <9>;
+ };
+
+ virtio_console@0600000 {
+ compatible = "virtio,mmio";
+ reg = <0 0x00600000 0x10000>;
+ interrupts = <10>;