kernel: add support for Raspberry Pi 2 and 3
Co-Authored-By: Benjamin Dauphin <benjamin.dauphin@live.fr> Co-Authored-By: Gilles Henaux <gill.henaux@gmail.com>
This commit is contained in:
parent
c5e7db6fac
commit
61569864b0
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -9,6 +9,7 @@ cscope.*
|
||||||
*.rej
|
*.rej
|
||||||
*.[1-9].gz
|
*.[1-9].gz
|
||||||
*.o
|
*.o
|
||||||
|
*.elf
|
||||||
*.[psS]o
|
*.[psS]o
|
||||||
*.pico
|
*.pico
|
||||||
lib*.so*
|
lib*.so*
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ set -e
|
||||||
|
|
||||||
exec >/dev/log
|
exec >/dev/log
|
||||||
exec 2>/dev/log
|
exec 2>/dev/log
|
||||||
exec </dev/null
|
exec </dev/console
|
||||||
|
|
||||||
FSCK=/bin/fsck_mfs
|
FSCK=/bin/fsck_mfs
|
||||||
ACPI=/service/acpi
|
ACPI=/service/acpi
|
||||||
|
|
@ -45,6 +45,12 @@ then if [ -e $ACPI -a -n "`sysenv acpi`" ]
|
||||||
/bin/umount /proc >/dev/null
|
/bin/umount /proc >/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# XXX: We don't have anything better to do on Raspberry Pi yet
|
||||||
|
if [ "$(/bin/sysenv board_name)" = "RPI_2_B" ] || [ "$(/bin/sysenv board_name)" = "RPI_3_B" ]
|
||||||
|
then
|
||||||
|
exec /bin/sh < /dev/console
|
||||||
|
fi
|
||||||
|
|
||||||
if [ X`/bin/sysenv arch` = Xearm ]
|
if [ X`/bin/sysenv arch` = Xearm ]
|
||||||
then echo Starting the mmc driver
|
then echo Starting the mmc driver
|
||||||
/bin/service -c up /service/mmc -dev /dev/c0d0
|
/bin/service -c up /service/mmc -dev /dev/c0d0
|
||||||
|
|
@ -88,7 +94,7 @@ fi
|
||||||
|
|
||||||
echo "Root device name is $rootdevname"
|
echo "Root device name is $rootdevname"
|
||||||
|
|
||||||
if ! sysenv cdproberoot >/dev/null
|
if (! sysenv cdproberoot) && (! sysenv bootramdisk) >/dev/null
|
||||||
then
|
then
|
||||||
if [ -e $FSCK ]
|
if [ -e $FSCK ]
|
||||||
then $FSCK -p $rootdevname
|
then $FSCK -p $rootdevname
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,6 @@
|
||||||
#ifndef _INTERRUPT_H
|
#ifndef _INTERRUPT_H
|
||||||
#define _INTERRUPT_H
|
#define _INTERRUPT_H
|
||||||
|
|
||||||
#define NR_IRQ_VECTORS 125
|
#define NR_IRQ_VECTORS 128
|
||||||
|
|
||||||
#endif /* _INTERRUPT_H */
|
#endif /* _INTERRUPT_H */
|
||||||
|
|
|
||||||
|
|
@ -67,12 +67,15 @@
|
||||||
|
|
||||||
#define MINIX_BOARD_VENDOR_INTEL MINIX_MK_BOARD_VENDOR(1<<0)
|
#define MINIX_BOARD_VENDOR_INTEL MINIX_MK_BOARD_VENDOR(1<<0)
|
||||||
#define MINIX_BOARD_VENDOR_TI MINIX_MK_BOARD_VENDOR(1<<1)
|
#define MINIX_BOARD_VENDOR_TI MINIX_MK_BOARD_VENDOR(1<<1)
|
||||||
|
#define MINIX_BOARD_VENDOR_RPI MINIX_MK_BOARD_VENDOR(1<<2)
|
||||||
|
|
||||||
#define MINIX_BOARD_GENERIC MINIX_MK_BOARD(1<<0)
|
#define MINIX_BOARD_GENERIC MINIX_MK_BOARD(1<<0)
|
||||||
/* BeagleBoard XM */
|
/* BeagleBoard XM */
|
||||||
#define MINIX_BOARD_BBXM MINIX_MK_BOARD(1<<1)
|
#define MINIX_BOARD_BBXM MINIX_MK_BOARD(1<<1)
|
||||||
/* BeagleBone (Black and* white) */
|
/* BeagleBone (Black and* white) */
|
||||||
#define MINIX_BOARD_BB MINIX_MK_BOARD(1<<2)
|
#define MINIX_BOARD_BB MINIX_MK_BOARD(1<<2)
|
||||||
|
/* Raspberry Pi */
|
||||||
|
#define MINIX_BOARD_RPI MINIX_MK_BOARD(1<<3)
|
||||||
|
|
||||||
/* Only one of a kind */
|
/* Only one of a kind */
|
||||||
#define MINIX_BOARD_VARIANT_GENERIC MINIX_MK_BOARD_VARIANT(1<<0)
|
#define MINIX_BOARD_VARIANT_GENERIC MINIX_MK_BOARD_VARIANT(1<<0)
|
||||||
|
|
@ -81,6 +84,10 @@
|
||||||
/* BeagleBone Black */
|
/* BeagleBone Black */
|
||||||
#define MINIX_BOARD_VARIANT_BBB MINIX_MK_BOARD_VARIANT(1<<2)
|
#define MINIX_BOARD_VARIANT_BBB MINIX_MK_BOARD_VARIANT(1<<2)
|
||||||
|
|
||||||
|
/* Rasberry Pi */
|
||||||
|
#define MINIX_BOARD_VARIANT_RPI_2_B MINIX_MK_BOARD_VARIANT(1<<1)
|
||||||
|
#define MINIX_BOARD_VARIANT_RPI_3_B MINIX_MK_BOARD_VARIANT(1<<2)
|
||||||
|
|
||||||
#define BOARD_ID_INTEL \
|
#define BOARD_ID_INTEL \
|
||||||
( MINIX_BOARD_ARCH_X86 \
|
( MINIX_BOARD_ARCH_X86 \
|
||||||
| MINIX_BOARD_ARCH_VARIANT_X86_GENERIC \
|
| MINIX_BOARD_ARCH_VARIANT_X86_GENERIC \
|
||||||
|
|
@ -113,6 +120,22 @@
|
||||||
| MINIX_BOARD_VARIANT_BBB\
|
| MINIX_BOARD_VARIANT_BBB\
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#define BOARD_ID_RPI_2_B \
|
||||||
|
( MINIX_BOARD_ARCH_ARM \
|
||||||
|
| MINIX_BOARD_ARCH_VARIANT_ARM_ARMV7 \
|
||||||
|
| MINIX_BOARD_VENDOR_RPI \
|
||||||
|
| MINIX_BOARD_RPI \
|
||||||
|
| MINIX_BOARD_VARIANT_RPI_2_B \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define BOARD_ID_RPI_3_B \
|
||||||
|
( MINIX_BOARD_ARCH_ARM \
|
||||||
|
| MINIX_BOARD_ARCH_VARIANT_ARM_ARMV7 \
|
||||||
|
| MINIX_BOARD_VENDOR_RPI \
|
||||||
|
| MINIX_BOARD_RPI \
|
||||||
|
| MINIX_BOARD_VARIANT_RPI_3_B \
|
||||||
|
)
|
||||||
|
|
||||||
#define BOARD_IS_BBXM(v) \
|
#define BOARD_IS_BBXM(v) \
|
||||||
( (BOARD_ID_BBXM & ~MINIX_BOARD_VARIANT_MASK) == (v & ~MINIX_BOARD_VARIANT_MASK))
|
( (BOARD_ID_BBXM & ~MINIX_BOARD_VARIANT_MASK) == (v & ~MINIX_BOARD_VARIANT_MASK))
|
||||||
/* Either one of the known BeagleBones */
|
/* Either one of the known BeagleBones */
|
||||||
|
|
@ -121,6 +144,9 @@
|
||||||
#define BOARD_IS_BBW(v) ( v == BOARD_ID_BBW)
|
#define BOARD_IS_BBW(v) ( v == BOARD_ID_BBW)
|
||||||
#define BOARD_IS_BBB(v) ( v == BOARD_ID_BBB)
|
#define BOARD_IS_BBB(v) ( v == BOARD_ID_BBB)
|
||||||
|
|
||||||
|
#define BOARD_IS_RPI_2_B(v) ( v == BOARD_ID_RPI_2_B)
|
||||||
|
#define BOARD_IS_RPI_3_B(v) ( v == BOARD_ID_RPI_3_B)
|
||||||
|
|
||||||
#define BOARD_FILTER_BBXM_VALUE (BOARD_ID_BBXM)
|
#define BOARD_FILTER_BBXM_VALUE (BOARD_ID_BBXM)
|
||||||
#define BOARD_FILTER_BBXM_MASK \
|
#define BOARD_FILTER_BBXM_MASK \
|
||||||
(MINIX_BOARD_ARCH_MASK \
|
(MINIX_BOARD_ARCH_MASK \
|
||||||
|
|
@ -148,6 +174,8 @@ static struct shortname2id shortname2id[] = {
|
||||||
{.name = "BBXM",.id = BOARD_ID_BBXM},
|
{.name = "BBXM",.id = BOARD_ID_BBXM},
|
||||||
{.name = "A335BONE",.id = BOARD_ID_BBW},
|
{.name = "A335BONE",.id = BOARD_ID_BBW},
|
||||||
{.name = "A335BNLT",.id = BOARD_ID_BBB},
|
{.name = "A335BNLT",.id = BOARD_ID_BBB},
|
||||||
|
{.name = "RPI_2_B",.id = BOARD_ID_RPI_2_B},
|
||||||
|
{.name = "RPI_3_B",.id = BOARD_ID_RPI_3_B},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct board_id2name
|
struct board_id2name
|
||||||
|
|
@ -162,6 +190,8 @@ static struct board_id2name board_id2name[] = {
|
||||||
{.id = BOARD_ID_BBXM,.name = "ARM-ARMV7-TI-BBXM-GENERIC"},
|
{.id = BOARD_ID_BBXM,.name = "ARM-ARMV7-TI-BBXM-GENERIC"},
|
||||||
{.id = BOARD_ID_BBW,.name = "ARM-ARMV7-TI-BB-WHITE"},
|
{.id = BOARD_ID_BBW,.name = "ARM-ARMV7-TI-BB-WHITE"},
|
||||||
{.id = BOARD_ID_BBB,.name = "ARM-ARMV7-TI-BB-BLACK"},
|
{.id = BOARD_ID_BBB,.name = "ARM-ARMV7-TI-BB-BLACK"},
|
||||||
|
{.id = BOARD_ID_RPI_2_B,.name = "ARM-ARMV7-RPI-RPI_2_B"},
|
||||||
|
{.id = BOARD_ID_RPI_3_B,.name = "ARM-ARMV7-RPI-RPI_3_B"},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct board_arch2arch
|
struct board_arch2arch
|
||||||
|
|
|
||||||
|
|
@ -319,4 +319,9 @@
|
||||||
#define CONTROL_CONF_PUDEN (1<<3)
|
#define CONTROL_CONF_PUDEN (1<<3)
|
||||||
#define CONTROL_CONF_MUXMODE(X) (X&0x7)
|
#define CONTROL_CONF_MUXMODE(X) (X&0x7)
|
||||||
|
|
||||||
|
/* Raspberry Pi specific registers */
|
||||||
|
#define PADCONF_RPI2_REGISTERS_BASE 0x3F200000
|
||||||
|
#define PADCONF_RPI2_REGISTERS_OFFSET 0x0000
|
||||||
|
#define PADCONF_RPI2_REGISTERS_SIZE 0x1000
|
||||||
|
|
||||||
#endif /* __MINIX_PADCONF_H */
|
#endif /* __MINIX_PADCONF_H */
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "bsp_timer.h"
|
#include "bsp_timer.h"
|
||||||
#include "bsp_intr.h"
|
#include "bsp_intr.h"
|
||||||
|
#include "cpufunc_timer.h"
|
||||||
|
|
||||||
static unsigned tsc_per_ms[CONFIG_MAX_CPUS];
|
static unsigned tsc_per_ms[CONFIG_MAX_CPUS];
|
||||||
static unsigned tsc_per_tick[CONFIG_MAX_CPUS];
|
static unsigned tsc_per_tick[CONFIG_MAX_CPUS];
|
||||||
|
|
@ -37,7 +38,11 @@ int init_local_timer(unsigned freq)
|
||||||
tsc_per_ms[0] = 16250;
|
tsc_per_ms[0] = 16250;
|
||||||
} else if (BOARD_IS_BB(machine.board_id)) {
|
} else if (BOARD_IS_BB(machine.board_id)) {
|
||||||
tsc_per_ms[0] = 15000;
|
tsc_per_ms[0] = 15000;
|
||||||
} else {
|
} else if (BOARD_IS_RPI_2_B(machine.board_id) ||
|
||||||
|
BOARD_IS_RPI_3_B(machine.board_id)) {
|
||||||
|
tsc_per_ms[0] = read_cntfrq() / 1000;
|
||||||
|
}
|
||||||
|
else {
|
||||||
panic("Can not do the clock setup. machine (0x%08x) is unknown\n",machine.board_id);
|
panic("Can not do the clock setup. machine (0x%08x) is unknown\n",machine.board_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
12
minix/kernel/arch/earm/bsp/rpi/Makefile.inc
Normal file
12
minix/kernel/arch/earm/bsp/rpi/Makefile.inc
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#
|
||||||
|
# BSP for RPI hardware
|
||||||
|
#
|
||||||
|
|
||||||
|
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/bsp/${BSP_NAME}
|
||||||
|
|
||||||
|
.for unpaged_obj in rpi_serial.o rpi_reset.o
|
||||||
|
BSP_OBJS_UNPAGED += ${unpaged_obj}
|
||||||
|
.endfor
|
||||||
|
|
||||||
|
SRCS+= rpi_init.c rpi_serial.c rpi_timer.c rpi_padconf.c rpi_intr.c \
|
||||||
|
rpi_reset.c
|
||||||
17
minix/kernel/arch/earm/bsp/rpi/rpi_init.c
Normal file
17
minix/kernel/arch/earm/bsp/rpi/rpi_init.c
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "bsp_init.h"
|
||||||
|
#include "bsp_padconf.h"
|
||||||
|
#include "bsp_reset.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_init()
|
||||||
|
{
|
||||||
|
/* map memory for padconf */
|
||||||
|
bsp_padconf_init();
|
||||||
|
|
||||||
|
/* map memory for reset control */
|
||||||
|
bsp_reset_init();
|
||||||
|
|
||||||
|
/* disable watchdog */
|
||||||
|
bsp_disable_watchdog();
|
||||||
|
}
|
||||||
140
minix/kernel/arch/earm/bsp/rpi/rpi_intr.c
Normal file
140
minix/kernel/arch/earm/bsp/rpi/rpi_intr.c
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <minix/type.h>
|
||||||
|
#include <minix/board.h>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
#include "kernel/proc.h"
|
||||||
|
#include "kernel/vm.h"
|
||||||
|
#include "kernel/proto.h"
|
||||||
|
#include "arch_proto.h"
|
||||||
|
#include "hw_intr.h"
|
||||||
|
|
||||||
|
#include "rpi_intr_registers.h"
|
||||||
|
#include "rpi_timer_registers.h"
|
||||||
|
|
||||||
|
static struct rpi2_intr
|
||||||
|
{
|
||||||
|
vir_bytes base;
|
||||||
|
vir_bytes core_base;
|
||||||
|
int size;
|
||||||
|
} rpi2_intr;
|
||||||
|
|
||||||
|
static kern_phys_map intr_phys_map;
|
||||||
|
static kern_phys_map timer_phys_map;
|
||||||
|
|
||||||
|
static irq_hook_t dummy8_irq_hook;
|
||||||
|
static irq_hook_t dummy41_irq_hook;
|
||||||
|
static irq_hook_t dummy51_irq_hook;
|
||||||
|
|
||||||
|
int
|
||||||
|
dummy_irq_handler()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The Raspberry Pi has a bunch of cascaded interrupts that are useless
|
||||||
|
* for MINIX. This handler catches them so as not to pollute the console
|
||||||
|
* with spurious interrupts messages.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
intr_init(const int auto_eoi)
|
||||||
|
{
|
||||||
|
if (BOARD_IS_RPI_2_B(machine.board_id) ||
|
||||||
|
BOARD_IS_RPI_3_B(machine.board_id)) {
|
||||||
|
rpi2_intr.base = RPI2_INTR_BASE;
|
||||||
|
rpi2_intr.core_base = RPI2_QA7_BASE;
|
||||||
|
} else {
|
||||||
|
panic
|
||||||
|
("Can not do the interrupt setup. machine (0x%08x) is unknown\n",
|
||||||
|
machine.board_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
rpi2_intr.size = 0x1000; /* 4K */
|
||||||
|
|
||||||
|
kern_phys_map_ptr(rpi2_intr.base, rpi2_intr.size,
|
||||||
|
VMMF_UNCACHED | VMMF_WRITE,
|
||||||
|
&intr_phys_map, (vir_bytes) & rpi2_intr.base);
|
||||||
|
kern_phys_map_ptr(rpi2_intr.core_base, rpi2_intr.size,
|
||||||
|
VMMF_UNCACHED | VMMF_WRITE,
|
||||||
|
&timer_phys_map, (vir_bytes) & rpi2_intr.core_base);
|
||||||
|
|
||||||
|
/* Disable FIQ and all interrupts */
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_FIQ_CTRL, 0);
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_DISABLE_BASIC, 0xFFFFFFFF);
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_DISABLE1, 0xFFFFFFFF);
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_DISABLE2, 0xFFFFFFFF);
|
||||||
|
|
||||||
|
/* Enable ARM timer routing to IRQ here */
|
||||||
|
mmio_write(rpi2_intr.core_base + QA7_CORE0TIMER, 0x8);
|
||||||
|
|
||||||
|
/* Register dummy irq handlers */
|
||||||
|
put_irq_handler(&dummy8_irq_hook, 8, (irq_handler_t)dummy_irq_handler);
|
||||||
|
put_irq_handler(&dummy41_irq_hook, 41, (irq_handler_t)dummy_irq_handler);
|
||||||
|
put_irq_handler(&dummy51_irq_hook, 51, (irq_handler_t)dummy_irq_handler);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_irq_handle(void)
|
||||||
|
{
|
||||||
|
/* Function called from assembly to handle interrupts */
|
||||||
|
uint32_t irq_0_31 = mmio_read(rpi2_intr.core_base + QA7_CORE0INT);
|
||||||
|
uint32_t irq_32_63 = mmio_read(rpi2_intr.base + RPI2_INTR_BASIC_PENDING);
|
||||||
|
uint32_t irq_64_95 = mmio_read(rpi2_intr.base + RPI2_INTR_PENDING1);
|
||||||
|
uint64_t irq_96_128 = mmio_read(rpi2_intr.base + RPI2_INTR_PENDING2);
|
||||||
|
|
||||||
|
int irq = 0;
|
||||||
|
|
||||||
|
/* Scan all interrupts bits */
|
||||||
|
for (irq = 0; irq < 128; irq++) {
|
||||||
|
int is_pending = 0;
|
||||||
|
if (irq < 32)
|
||||||
|
is_pending = irq_0_31 & (1 << irq);
|
||||||
|
else if (irq < 64)
|
||||||
|
is_pending = irq_32_63 & (1 << (irq-32));
|
||||||
|
else if (irq < 96)
|
||||||
|
is_pending = irq_64_95 & (1 << (irq-64));
|
||||||
|
else
|
||||||
|
is_pending = irq_96_128 & (1 << (irq-96));
|
||||||
|
|
||||||
|
if (is_pending)
|
||||||
|
irq_handle(irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear all pending interrupts */
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_BASIC_PENDING, irq_32_63);
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_PENDING1, irq_64_95);
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_PENDING2, irq_96_128);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_irq_unmask(int irq)
|
||||||
|
{
|
||||||
|
if (irq < 32)
|
||||||
|
/* Nothing to do */
|
||||||
|
;
|
||||||
|
else if (irq < 64)
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_ENABLE_BASIC, 1 << (irq-32));
|
||||||
|
else if (irq < 96)
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_ENABLE1, 1 << (irq-64));
|
||||||
|
else if (irq < 128)
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_ENABLE2, 1 << (irq-96));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_irq_mask(const int irq)
|
||||||
|
{
|
||||||
|
if (irq < 32)
|
||||||
|
/* Nothing to do */
|
||||||
|
;
|
||||||
|
else if (irq < 64)
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_DISABLE_BASIC, 1 << (irq-32));
|
||||||
|
else if (irq < 96)
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_DISABLE1, 1 << (irq-64));
|
||||||
|
else if (irq < 128)
|
||||||
|
mmio_write(rpi2_intr.base + RPI2_INTR_DISABLE2, 1 << (irq-96));
|
||||||
|
}
|
||||||
17
minix/kernel/arch/earm/bsp/rpi/rpi_intr_registers.h
Normal file
17
minix/kernel/arch/earm/bsp/rpi/rpi_intr_registers.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _RPI_INTR_H
|
||||||
|
#define _RPI_INTR_H
|
||||||
|
|
||||||
|
#define RPI2_INTR_BASE 0x3f00B000
|
||||||
|
|
||||||
|
#define RPI2_INTR_BASIC_PENDING 0x200
|
||||||
|
#define RPI2_INTR_PENDING1 0x204
|
||||||
|
#define RPI2_INTR_PENDING2 0x208
|
||||||
|
#define RPI2_INTR_FIQ_CTRL 0x20c
|
||||||
|
#define RPI2_INTR_ENABLE1 0x210
|
||||||
|
#define RPI2_INTR_ENABLE2 0x214
|
||||||
|
#define RPI2_INTR_ENABLE_BASIC 0x218
|
||||||
|
#define RPI2_INTR_DISABLE1 0x21c
|
||||||
|
#define RPI2_INTR_DISABLE2 0x220
|
||||||
|
#define RPI2_INTR_DISABLE_BASIC 0x224
|
||||||
|
|
||||||
|
#endif /* _RPI_INTR_H */
|
||||||
58
minix/kernel/arch/earm/bsp/rpi/rpi_padconf.c
Normal file
58
minix/kernel/arch/earm/bsp/rpi/rpi_padconf.c
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* Implements sys_padconf() for the Raspberry Pi. */
|
||||||
|
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
#include "arch_proto.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <minix/mmio.h>
|
||||||
|
#include <minix/padconf.h>
|
||||||
|
#include <minix/board.h>
|
||||||
|
#include <minix/com.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "bsp_padconf.h"
|
||||||
|
|
||||||
|
struct rpi2_padconf
|
||||||
|
{
|
||||||
|
vir_bytes base;
|
||||||
|
vir_bytes offset;
|
||||||
|
vir_bytes size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rpi2_padconf rpi2_padconf;
|
||||||
|
|
||||||
|
static kern_phys_map padconf_phys_map;
|
||||||
|
|
||||||
|
int
|
||||||
|
bsp_padconf_set(u32_t padconf, u32_t mask, u32_t value)
|
||||||
|
{
|
||||||
|
/* check that the value will be inside the padconf memory range */
|
||||||
|
if (padconf >= (rpi2_padconf.size - rpi2_padconf.offset)) {
|
||||||
|
return EINVAL; /* outside of valid range */
|
||||||
|
}
|
||||||
|
|
||||||
|
set32(padconf + rpi2_padconf.base + rpi2_padconf.offset, mask,
|
||||||
|
value);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_padconf_init(void)
|
||||||
|
{
|
||||||
|
if (BOARD_IS_RPI_2_B(machine.board_id) ||
|
||||||
|
BOARD_IS_RPI_3_B(machine.board_id)) {
|
||||||
|
rpi2_padconf.base = PADCONF_RPI2_REGISTERS_BASE;
|
||||||
|
rpi2_padconf.offset = PADCONF_RPI2_REGISTERS_OFFSET;
|
||||||
|
rpi2_padconf.size = PADCONF_RPI2_REGISTERS_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_phys_map_ptr(rpi2_padconf.base, rpi2_padconf.size,
|
||||||
|
VMMF_UNCACHED | VMMF_WRITE,
|
||||||
|
&padconf_phys_map, (vir_bytes) & rpi2_padconf.base);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
33
minix/kernel/arch/earm/bsp/rpi/rpi_reset.c
Normal file
33
minix/kernel/arch/earm/bsp/rpi/rpi_reset.c
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <minix/type.h>
|
||||||
|
#include <minix/board.h>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
#include "kernel/proc.h"
|
||||||
|
#include "kernel/vm.h"
|
||||||
|
#include "kernel/proto.h"
|
||||||
|
#include "arch_proto.h"
|
||||||
|
#include "bsp_reset.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_reset_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_reset(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_poweroff(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp_disable_watchdog(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
95
minix/kernel/arch/earm/bsp/rpi/rpi_serial.c
Normal file
95
minix/kernel/arch/earm/bsp/rpi/rpi_serial.c
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <minix/type.h>
|
||||||
|
#include <minix/board.h>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
#include "kernel/proc.h"
|
||||||
|
#include "kernel/vm.h"
|
||||||
|
#include "kernel/proto.h"
|
||||||
|
#include "arch_proto.h"
|
||||||
|
|
||||||
|
#include "rpi_serial.h"
|
||||||
|
|
||||||
|
struct pl011_serial
|
||||||
|
{
|
||||||
|
vir_bytes base;
|
||||||
|
vir_bytes size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pl011_serial pl011_serial = {
|
||||||
|
.base = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static kern_phys_map serial_phys_map;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In kernel serial for the RPi. The serial driver like most other
|
||||||
|
* drivers needs to be started early and even before the MMU is turned on.
|
||||||
|
* We start by directly accessing the hardware memory address. Later on
|
||||||
|
* when the MMU is turned on we still use a 1:1 mapping for these addresses.
|
||||||
|
*
|
||||||
|
* Pretty soon we are going to remap these addresses at later stage. And this
|
||||||
|
* requires us to use a dynamic base address. The idea is to receive a callback
|
||||||
|
* from VM with the new address to use.
|
||||||
|
*
|
||||||
|
* The serial driver also gets used in the "pre_init" stage before the kernel is loaded
|
||||||
|
* in high memory so keep in mind there are two copies of this code in the kernel.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
bsp_ser_init()
|
||||||
|
{
|
||||||
|
if (BOARD_IS_RPI_2_B(machine.board_id) ||
|
||||||
|
BOARD_IS_RPI_3_B(machine.board_id)) {
|
||||||
|
pl011_serial.base = RPI2_PL011_DEBUG_UART_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl011_serial.size = 0x1000; /* 4k */
|
||||||
|
|
||||||
|
kern_phys_map_ptr(pl011_serial.base, pl011_serial.size,
|
||||||
|
VMMF_UNCACHED | VMMF_WRITE, &serial_phys_map,
|
||||||
|
(vir_bytes) & pl011_serial.base);
|
||||||
|
|
||||||
|
assert(pl011_serial.base);
|
||||||
|
|
||||||
|
/* Set UART to 115200 bauds */
|
||||||
|
if (BOARD_IS_RPI_2_B(machine.board_id)) {
|
||||||
|
/* UARTCLK=48MHz */
|
||||||
|
mmio_write(pl011_serial.base + PL011_IBRD, 1);
|
||||||
|
mmio_write(pl011_serial.base + PL011_FBRD, 40);
|
||||||
|
}
|
||||||
|
else if (BOARD_IS_RPI_3_B(machine.board_id)) {
|
||||||
|
/* UARTCLK=3MHz */
|
||||||
|
mmio_write(pl011_serial.base + PL011_IBRD, 26);
|
||||||
|
mmio_write(pl011_serial.base + PL011_FBRD, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
mmio_write(pl011_serial.base + PL011_LCRH, 0x70);
|
||||||
|
mmio_write(pl011_serial.base + PL011_CR, 0x301);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_ser_putc(char c)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
assert(pl011_serial.base);
|
||||||
|
|
||||||
|
/* Wait until FIFO's not full */
|
||||||
|
for (i = 0; i < 100000; i++) {
|
||||||
|
if ((mmio_read(pl011_serial.base + PL011_FR) & PL011_FR_TXFF) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write character */
|
||||||
|
mmio_write(pl011_serial.base + PL011_DR, c);
|
||||||
|
|
||||||
|
/* And wait again until FIFO's empty to prevent TTY from overwriting */
|
||||||
|
for (i = 0; i < 100000; i++) {
|
||||||
|
if (mmio_read(pl011_serial.base + PL011_FR) & PL011_FR_TXFE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
minix/kernel/arch/earm/bsp/rpi/rpi_serial.h
Normal file
23
minix/kernel/arch/earm/bsp/rpi/rpi_serial.h
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef _RPI_SERIAL_H
|
||||||
|
#define _RPI_SERIAL_H
|
||||||
|
|
||||||
|
#define RPI2_PL011_DEBUG_UART_BASE 0x3f201000
|
||||||
|
|
||||||
|
#define PL011_DR 0x0
|
||||||
|
#define PL011_FR 0x18
|
||||||
|
#define PL011_IBRD 0x24
|
||||||
|
#define PL011_FBRD 0x28
|
||||||
|
#define PL011_LCRH 0x2c
|
||||||
|
#define PL011_CR 0x30
|
||||||
|
|
||||||
|
#define PL011_FR_TXFF (1<<5)
|
||||||
|
#define PL011_FR_TXFE (1<<7)
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
void bsp_ser_init();
|
||||||
|
void bsp_ser_putc(char c);
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
|
#endif /* _RPI_SERIAL_H */
|
||||||
85
minix/kernel/arch/earm/bsp/rpi/rpi_timer.c
Normal file
85
minix/kernel/arch/earm/bsp/rpi/rpi_timer.c
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
#include "kernel/clock.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <minix/board.h>
|
||||||
|
#include <minix/mmio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "arch_proto.h"
|
||||||
|
#include "bsp_timer.h"
|
||||||
|
#include "rpi_timer_registers.h"
|
||||||
|
#include "rpi_intr_registers.h"
|
||||||
|
#include "bsp_intr.h"
|
||||||
|
|
||||||
|
#include "cpufunc_timer.h"
|
||||||
|
|
||||||
|
static irq_hook_t arm_timer_hook;
|
||||||
|
|
||||||
|
struct arm_timer
|
||||||
|
{
|
||||||
|
int irq_nr;
|
||||||
|
u32_t freq;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct arm_timer arm_timer = {
|
||||||
|
.irq_nr = RPI2_IRQ_ARMTIMER,
|
||||||
|
.freq = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static kern_phys_map stc_timer_phys_map;
|
||||||
|
|
||||||
|
int
|
||||||
|
bsp_register_timer_handler(const irq_handler_t handler)
|
||||||
|
{
|
||||||
|
/* Initialize the CLOCK's interrupt hook. */
|
||||||
|
arm_timer_hook.proc_nr_e = NONE;
|
||||||
|
arm_timer_hook.irq = arm_timer.irq_nr;
|
||||||
|
|
||||||
|
put_irq_handler(&arm_timer_hook, arm_timer.irq_nr, handler);
|
||||||
|
|
||||||
|
/* Prepare next firing of timer */
|
||||||
|
bsp_timer_int_handler();
|
||||||
|
|
||||||
|
/* only unmask interrupts after registering */
|
||||||
|
bsp_irq_unmask(arm_timer.irq_nr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* callback for when the free running clock gets mapped */
|
||||||
|
int
|
||||||
|
kern_phys_fr_user_mapped(vir_bytes id, phys_bytes address)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_timer_init(unsigned freq)
|
||||||
|
{
|
||||||
|
arm_timer.freq = freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_timer_stop()
|
||||||
|
{
|
||||||
|
bsp_irq_mask(arm_timer.irq_nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_timer_int_handler()
|
||||||
|
{
|
||||||
|
/* Arm next timer countdown and enable timer */
|
||||||
|
write_cntv_cval(-1);
|
||||||
|
write_cntv_tval(read_cntfrq() / arm_timer.freq);
|
||||||
|
write_cntv_ctl(ARMTIMER_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use the free running clock as TSC */
|
||||||
|
void
|
||||||
|
read_tsc_64(u64_t * t)
|
||||||
|
{
|
||||||
|
*t = read_cntv_cval();
|
||||||
|
}
|
||||||
11
minix/kernel/arch/earm/bsp/rpi/rpi_timer_registers.h
Normal file
11
minix/kernel/arch/earm/bsp/rpi/rpi_timer_registers.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef _RPI_TIMER_REGISTERS_H
|
||||||
|
#define _RPI_TIMER_REGISTERS_H
|
||||||
|
|
||||||
|
#define RPI2_QA7_BASE 0x40000000
|
||||||
|
|
||||||
|
#define QA7_CORE0TIMER 0x40
|
||||||
|
#define QA7_CORE0INT 0x60
|
||||||
|
|
||||||
|
#define RPI2_IRQ_ARMTIMER 3
|
||||||
|
|
||||||
|
#endif /* _RPI_TIMER_REGISTERS_H */
|
||||||
67
minix/kernel/arch/earm/include/cpufunc_timer.h
Normal file
67
minix/kernel/arch/earm/include/cpufunc_timer.h
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef _ARM_CPUFUNC_TIMER_H
|
||||||
|
#define _ARM_CPUFUNC_TIMER_H
|
||||||
|
|
||||||
|
/* Read CNTFRQ */
|
||||||
|
static inline u32_t read_cntfrq() {
|
||||||
|
u32_t cntfrq;
|
||||||
|
asm volatile("mrc p15, 0, %[cntfrq], c14, c0 , 0 @ READ CNTFRQ\n\t"
|
||||||
|
: [cntfrq] "=r" (cntfrq));
|
||||||
|
return cntfrq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read CNTV_TVAL, virtual timer value register */
|
||||||
|
static inline i32_t read_cntv_tval() {
|
||||||
|
i32_t cntv_tval;
|
||||||
|
asm volatile("mrc p15, 0, %[cntv_tval], c14, c3 , 0 @ READ CNTV_TVAL\n\t"
|
||||||
|
: [cntv_tval] "=r" (cntv_tval));
|
||||||
|
return cntv_tval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write CNTV_TVAL, virtual timer control register */
|
||||||
|
static inline void write_cntv_tval(i32_t val) {
|
||||||
|
asm volatile("mcr p15, 0, %[val], c14, c3 , 0 @ WRITE CNTV_CTL\n\t"
|
||||||
|
: : [val] "r" (val));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read CNTV_CTL, virtual timer control register */
|
||||||
|
static inline u32_t read_cntv_ctl() {
|
||||||
|
u32_t cntv_ctl;
|
||||||
|
asm volatile("mrc p15, 0, %[cntv_ctl], c14, c3 , 1 @ READ CNTV_CTL\n\t"
|
||||||
|
: [cntv_ctl] "=r" (cntv_ctl));
|
||||||
|
return cntv_ctl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write CNTV_CTL, virtual timer control register */
|
||||||
|
static inline void write_cntv_ctl(u32_t val) {
|
||||||
|
asm volatile("mcr p15, 0, %[val], c14, c3 , 1 @ WRITE CNTV_CTL\n\t"
|
||||||
|
: : [val] "r" (val));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read CNTV_CVAL, virtual timer compare value register */
|
||||||
|
static inline u64_t read_cntv_cval() {
|
||||||
|
u32_t cntv_cval_lo, cntv_cval_hi;
|
||||||
|
asm volatile("mrrc p15, 3, %[cntv_cval_lo], %[cntv_cval_hi], c14 @ READ CNTV_CVAL\n\t"
|
||||||
|
: [cntv_cval_lo] "=r" (cntv_cval_lo), [cntv_cval_hi] "=r" (cntv_cval_hi));
|
||||||
|
return ((u64_t)cntv_cval_hi) << 32 | cntv_cval_lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write CNTV_CVAL, virtual timer compare value register */
|
||||||
|
static inline void write_cntv_cval(u64_t val) {
|
||||||
|
u32_t cntv_cval_lo = val & 0xFFFFFFFF, cntv_cval_hi = val >> 32;
|
||||||
|
asm volatile("mcrr p15, 3, %[cntv_cval_lo], %[cntv_cval_hi], c14 @ WRITE CNTV_CVAL\n\t"
|
||||||
|
: : [cntv_cval_lo] "r" (cntv_cval_lo), [cntv_cval_hi] "r" (cntv_cval_hi));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read CNTVCT, virtual count register */
|
||||||
|
static inline u64_t read_cntvct() {
|
||||||
|
u32_t cntvct_lo, cntvct_hi;
|
||||||
|
asm volatile("mrrc p15, 1, %[cntvct_lo], %[cntvct_hi], c14 @ READ CNTVCT\n\t"
|
||||||
|
: [cntvct_lo] "=r" (cntvct_lo), [cntvct_hi] "=r" (cntvct_hi));
|
||||||
|
return ((u64_t)cntvct_hi) << 32 | cntvct_lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ARMTIMER_ENABLE 0x1
|
||||||
|
#define ARMTIMER_IMASK 0x2
|
||||||
|
#define ARMTIMER_ISTATUS 0x4
|
||||||
|
|
||||||
|
#endif /* _ARM_CPUFUNC_TIMER_H */
|
||||||
50
minix/kernel/arch/earm/kernel-rpi.lds
Normal file
50
minix/kernel/arch/earm/kernel-rpi.lds
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
OUTPUT_ARCH("arm")
|
||||||
|
ENTRY(__k_unpaged_MINIX)
|
||||||
|
|
||||||
|
_kern_phys_base = 0x00200000; /* phys 4MB aligned for convenient remapping */
|
||||||
|
_kern_vir_base = 0xF0400000; /* map kernel high for max. user vir space */
|
||||||
|
_kern_offset = (_kern_vir_base - _kern_phys_base);
|
||||||
|
|
||||||
|
__k_unpaged__kern_offset = _kern_offset;
|
||||||
|
__k_unpaged__kern_vir_base = _kern_vir_base;
|
||||||
|
__k_unpaged__kern_phys_base = _kern_phys_base;
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = _kern_phys_base;
|
||||||
|
__k_unpaged__kern_unpaged_start = .;
|
||||||
|
|
||||||
|
.unpaged_text ALIGN(4096) : { unpaged_*.o(.startup); unpaged_*.o(.text) }
|
||||||
|
.unpaged_data ALIGN(4096) : { unpaged_*.o(.data .rodata*) }
|
||||||
|
__k_unpaged__kern_unpaged_edata = .;
|
||||||
|
|
||||||
|
.unpaged_bss ALIGN(4096) : { unpaged_*.o(.bss COMMON) }
|
||||||
|
__k_unpaged__kern_unpaged_end = .;
|
||||||
|
|
||||||
|
. += _kern_offset;
|
||||||
|
|
||||||
|
. = ALIGN(4096); usermapped_start = .;
|
||||||
|
.usermapped_glo : AT(ADDR(.usermapped_glo) - _kern_offset) { *(.usermapped_glo) }
|
||||||
|
. = ALIGN(4096); usermapped_nonglo_start = .;
|
||||||
|
.usermapped : AT(ADDR(.usermapped) - _kern_offset) { *(.usermapped) }
|
||||||
|
. = ALIGN(4096); usermapped_end = .;
|
||||||
|
.text : AT(ADDR(.text) - _kern_offset) { *(.text*) }
|
||||||
|
_etext = .;
|
||||||
|
.data ALIGN(4096) : AT(ADDR(.data) - _kern_offset) { *(.data .rodata* ) }
|
||||||
|
. = ALIGN(4096);
|
||||||
|
_edata = .;
|
||||||
|
__k_unpaged__edata = . - _kern_offset;
|
||||||
|
.bss ALIGN(4096) : AT(ADDR(.bss) - _kern_offset) { *(.bss* COMMON)
|
||||||
|
__k_unpaged__kern_size = . - _kern_vir_base;
|
||||||
|
_kern_size = __k_unpaged__kern_size;
|
||||||
|
|
||||||
|
. += 4096;
|
||||||
|
}
|
||||||
|
_end = .;
|
||||||
|
__k_unpaged__end = . - _kern_offset;
|
||||||
|
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
*(.ARM.exidx*)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,6 +31,10 @@ void get_phys_mem_map(phys_bytes *start, phys_bytes *end)
|
||||||
*start = 0x80000000;
|
*start = 0x80000000;
|
||||||
*end = 0xbfffffff;
|
*end = 0xbfffffff;
|
||||||
}
|
}
|
||||||
|
else if (BOARD_IS_RPI_2_B(machine.board_id) || BOARD_IS_RPI_3_B(machine.board_id)) {
|
||||||
|
*start = 0x00000000;
|
||||||
|
*end = 0x3effffff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_memmap(kinfo_t *cbi)
|
void print_memmap(kinfo_t *cbi)
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,11 @@ void setup_mbi(multiboot_info_t *mbi, char *bootargs)
|
||||||
mb_mmap_start = 0x80000000;
|
mb_mmap_start = 0x80000000;
|
||||||
mb_mmap_size = 0x10000000; /* 256 MB */
|
mb_mmap_size = 0x10000000; /* 256 MB */
|
||||||
}
|
}
|
||||||
|
else if (BOARD_IS_RPI_2_B(machine.board_id) || BOARD_IS_RPI_3_B(machine.board_id)) {
|
||||||
|
mb_mods_base = 0x02000000;
|
||||||
|
mb_mmap_start = 0x00008000; /* Don't overwrite bootcode for secondary CPUs */
|
||||||
|
mb_mmap_size = 0x3C000000 - 0x00008000; /* 960 MB */
|
||||||
|
}
|
||||||
else
|
else
|
||||||
POORMANS_FAILURE_NOTIFICATION;
|
POORMANS_FAILURE_NOTIFICATION;
|
||||||
|
|
||||||
|
|
|
||||||
151
releasetools/arm_sdimage_rpi.sh
Executable file
151
releasetools/arm_sdimage_rpi.sh
Executable file
|
|
@ -0,0 +1,151 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script creates a bootable image and should at some point in the future
|
||||||
|
# be replaced by the proper NetBSD infrastructure.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Source settings if present
|
||||||
|
#
|
||||||
|
: ${SETTINGS_MINIX=.settings}
|
||||||
|
if [ -f "${SETTINGS_MINIX}" ]
|
||||||
|
then
|
||||||
|
echo "Sourcing settings from ${SETTINGS_MINIX}"
|
||||||
|
# Display the content (so we can check in the build logs
|
||||||
|
# what the settings contain.
|
||||||
|
cat ${SETTINGS_MINIX} | sed "s,^,CONTENT ,g"
|
||||||
|
. ${SETTINGS_MINIX}
|
||||||
|
fi
|
||||||
|
|
||||||
|
BSP_NAME=rpi
|
||||||
|
: ${ARCH=evbearm-el}
|
||||||
|
: ${TOOLCHAIN_TRIPLET=arm-elf32-minix-}
|
||||||
|
: ${BUILDSH=build.sh}
|
||||||
|
|
||||||
|
: ${SETS="minix-base"}
|
||||||
|
: ${IMG=minix_arm_sd_rpi.img}
|
||||||
|
|
||||||
|
# ARM definitions:
|
||||||
|
: ${BUILDVARS=-V MKGCCCMDS=yes -V MKLLVM=no}
|
||||||
|
# These BUILDVARS are for building with LLVM:
|
||||||
|
#: ${BUILDVARS=-V MKLIBCXX=no -V MKKYUA=no -V MKATF=no -V MKLLVMCMDS=no}
|
||||||
|
|
||||||
|
if [ ! -f ${BUILDSH} ]
|
||||||
|
then
|
||||||
|
echo "Please invoke me from the root source dir, where ${BUILDSH} is."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# we create a disk image of about 2 gig's
|
||||||
|
# for alignment reasons, prefer sizes which are multiples of 4096 bytes
|
||||||
|
: ${FAT_START=4096}
|
||||||
|
: ${FAT_SIZE=$(( 64*(2**20) - ${FAT_START} ))}
|
||||||
|
: ${ROOT_SIZE=$(( 64*(2**20) ))}
|
||||||
|
: ${HOME_SIZE=$(( 128*(2**20) ))}
|
||||||
|
: ${USR_SIZE=$(( 1792*(2**20) ))}
|
||||||
|
#: ${IMG_SIZE=$(( 2*(2**30) ))} # no need to build an image that big for now
|
||||||
|
: ${IMG_SIZE=$(( 64*(2**20) ))}
|
||||||
|
|
||||||
|
# set up disk creation environment
|
||||||
|
. releasetools/image.defaults
|
||||||
|
. releasetools/image.functions
|
||||||
|
|
||||||
|
${RELEASETOOLSDIR}/checkout_repo.sh -o ${RELEASETOOLSDIR}/rpi-firmware -b ${RPI_FIRMWARE_BRANCH} -n ${RPI_FIRMWARE_REVISION} ${RPI_FIRMWARE_URL}
|
||||||
|
|
||||||
|
# where the kernel & boot modules will be
|
||||||
|
MODDIR=${DESTDIR}/boot/minix/.temp
|
||||||
|
|
||||||
|
echo "Building work directory..."
|
||||||
|
build_workdir "$SETS"
|
||||||
|
|
||||||
|
# IMG might be a block device
|
||||||
|
if [ -f ${IMG} ]
|
||||||
|
then
|
||||||
|
rm -f ${IMG}
|
||||||
|
fi
|
||||||
|
dd if=/dev/zero of=${IMG} bs=512 count=1 seek=$((($IMG_SIZE / 512) -1)) 2>/dev/null
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate /root, /usr and /home partition images.
|
||||||
|
#
|
||||||
|
echo "Writing disk image..."
|
||||||
|
|
||||||
|
#
|
||||||
|
# Write FAT bootloader partition
|
||||||
|
#
|
||||||
|
echo " * BOOT"
|
||||||
|
rm -rf ${ROOT_DIR}/*
|
||||||
|
# copy over all modules
|
||||||
|
for i in ${MODDIR}/*
|
||||||
|
do
|
||||||
|
cp $i ${ROOT_DIR}/$(basename $i).elf
|
||||||
|
done
|
||||||
|
${CROSS_PREFIX}objcopy ${OBJ}/minix/kernel/kernel -O binary ${ROOT_DIR}/kernel.bin
|
||||||
|
# create packer
|
||||||
|
${CROSS_PREFIX}as ${RELEASETOOLSDIR}/rpi-bootloader/bootloader2.S -o ${RELEASETOOLSDIR}/rpi-bootloader/bootloader2.o
|
||||||
|
${CROSS_PREFIX}as ${RELEASETOOLSDIR}/rpi-bootloader/bootloader3.S -o ${RELEASETOOLSDIR}/rpi-bootloader/bootloader3.o
|
||||||
|
${CROSS_PREFIX}ld ${RELEASETOOLSDIR}/rpi-bootloader/bootloader2.o -o ${RELEASETOOLSDIR}/rpi-bootloader/bootloader2.elf -Ttext=0x8000 2> /dev/null
|
||||||
|
${CROSS_PREFIX}ld ${RELEASETOOLSDIR}/rpi-bootloader/bootloader3.o -o ${RELEASETOOLSDIR}/rpi-bootloader/bootloader3.elf -Ttext=0x8000 2> /dev/null
|
||||||
|
${CROSS_PREFIX}objcopy -O binary ${RELEASETOOLSDIR}/rpi-bootloader/bootloader2.elf ${ROOT_DIR}/minix_rpi2.bin
|
||||||
|
${CROSS_PREFIX}objcopy -O binary ${RELEASETOOLSDIR}/rpi-bootloader/bootloader3.elf ${ROOT_DIR}/minix_rpi3.bin
|
||||||
|
# pack modules
|
||||||
|
(cd ${ROOT_DIR} && cat <<EOF | cpio -o --format=newc >> ${ROOT_DIR}/minix_rpi2.bin 2>/dev/null
|
||||||
|
kernel.bin
|
||||||
|
mod01_ds.elf
|
||||||
|
mod02_rs.elf
|
||||||
|
mod03_pm.elf
|
||||||
|
mod04_sched.elf
|
||||||
|
mod05_vfs.elf
|
||||||
|
mod06_memory.elf
|
||||||
|
mod07_tty.elf
|
||||||
|
mod08_mib.elf
|
||||||
|
mod09_vm.elf
|
||||||
|
mod10_pfs.elf
|
||||||
|
mod11_mfs.elf
|
||||||
|
mod12_init.elf
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
(cd ${ROOT_DIR} && cat <<EOF | cpio -o --format=newc >> ${ROOT_DIR}/minix_rpi3.bin 2>/dev/null
|
||||||
|
kernel.bin
|
||||||
|
mod01_ds.elf
|
||||||
|
mod02_rs.elf
|
||||||
|
mod03_pm.elf
|
||||||
|
mod04_sched.elf
|
||||||
|
mod05_vfs.elf
|
||||||
|
mod06_memory.elf
|
||||||
|
mod07_tty.elf
|
||||||
|
mod08_mib.elf
|
||||||
|
mod09_vm.elf
|
||||||
|
mod10_pfs.elf
|
||||||
|
mod11_mfs.elf
|
||||||
|
mod12_init.elf
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
cp -r releasetools/rpi-firmware/* ${ROOT_DIR}
|
||||||
|
|
||||||
|
# Write GPU config file
|
||||||
|
cat <<EOF >${ROOT_DIR}/config.txt
|
||||||
|
[pi3]
|
||||||
|
kernel=minix_rpi3.bin
|
||||||
|
enable_uart=1
|
||||||
|
dtoverlay=pi3-disable-bt
|
||||||
|
|
||||||
|
[pi2]
|
||||||
|
kernel=minix_rpi2.bin
|
||||||
|
EOF
|
||||||
|
|
||||||
|
${CROSS_TOOLS}/nbmakefs -t msdos -s $FAT_SIZE -O $FAT_START -o "F=32,c=1" ${IMG} ${ROOT_DIR} >/dev/null
|
||||||
|
|
||||||
|
#
|
||||||
|
# Write the partition table using the natively compiled
|
||||||
|
# minix partition utility
|
||||||
|
#
|
||||||
|
${CROSS_TOOLS}/nbpartition -f -m ${IMG} $((${FAT_START}/512)) "c:$((${FAT_SIZE}/512))*"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Disk image at `pwd`/${IMG}"
|
||||||
|
echo ""
|
||||||
|
echo "To boot this image on kvm:"
|
||||||
|
echo "qemu-system-arm -M raspi2 -drive if=sd,cache=writeback,format=raw,file=$(pwd)/${IMG} -bios ${ROOT_DIR}/minix_rpi2.bin"
|
||||||
|
|
@ -33,3 +33,7 @@ MODDIR=${DESTDIR}/boot/minix/.temp
|
||||||
: ${U_BOOT_URL=git://git.minix3.org/u-boot}
|
: ${U_BOOT_URL=git://git.minix3.org/u-boot}
|
||||||
: ${U_BOOT_BRANCH=minix}
|
: ${U_BOOT_BRANCH=minix}
|
||||||
: ${U_BOOT_REVISION=cb5178f12787c690cb1c888d88733137e5a47b15}
|
: ${U_BOOT_REVISION=cb5178f12787c690cb1c888d88733137e5a47b15}
|
||||||
|
|
||||||
|
: ${RPI_FIRMWARE_URL=https://github.com/boricj/rpi-firmware.git}
|
||||||
|
: ${RPI_FIRMWARE_BRANCH=master}
|
||||||
|
: ${RPI_FIRMWARE_REVISION=ccbca2eadd09dc550968839f227ecd0323cdbf22}
|
||||||
|
|
|
||||||
18
releasetools/rpi-bootloader/bootloader2.S
Normal file
18
releasetools/rpi-bootloader/bootloader2.S
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
.text
|
||||||
|
|
||||||
|
.include "releasetools/rpi-bootloader/bootloader_common.S"
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
argv:
|
||||||
|
.word argv0
|
||||||
|
.word argv1
|
||||||
|
.word 0x0
|
||||||
|
argv0:
|
||||||
|
.asciz "0x00200000"
|
||||||
|
argv1:
|
||||||
|
.asciz "board_name=RPI_2_B console=tty00"
|
||||||
|
|
||||||
|
.data
|
||||||
|
.align 4
|
||||||
|
.space 256
|
||||||
|
stack_top:
|
||||||
18
releasetools/rpi-bootloader/bootloader3.S
Normal file
18
releasetools/rpi-bootloader/bootloader3.S
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
.text
|
||||||
|
|
||||||
|
.include "releasetools/rpi-bootloader/bootloader_common.S"
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
argv:
|
||||||
|
.word argv0
|
||||||
|
.word argv1
|
||||||
|
.word 0x0
|
||||||
|
argv0:
|
||||||
|
.asciz "0x00200000"
|
||||||
|
argv1:
|
||||||
|
.asciz "board_name=RPI_3_B console=tty00"
|
||||||
|
|
||||||
|
.data
|
||||||
|
.align 4
|
||||||
|
.space 256
|
||||||
|
stack_top:
|
||||||
332
releasetools/rpi-bootloader/bootloader_common.S
Normal file
332
releasetools/rpi-bootloader/bootloader_common.S
Normal file
|
|
@ -0,0 +1,332 @@
|
||||||
|
_start:
|
||||||
|
ldr sp, =stack_top
|
||||||
|
|
||||||
|
/* Print banner */
|
||||||
|
ldr r0, =msg_empty
|
||||||
|
bl puts
|
||||||
|
ldr r0, =msg_empty
|
||||||
|
bl puts
|
||||||
|
ldr r0, =msg_banner
|
||||||
|
bl puts
|
||||||
|
|
||||||
|
/* Check if in hypervisor mode */
|
||||||
|
mrs r0, cpsr
|
||||||
|
and r1, r0, #0x1f
|
||||||
|
cmp r1, #0x1a
|
||||||
|
bne mode_svc
|
||||||
|
|
||||||
|
mode_hyp:
|
||||||
|
/* In hypervisor mode */
|
||||||
|
ldr r0, =msg_hypmode
|
||||||
|
bl puts
|
||||||
|
|
||||||
|
movw r0, #0x1d3
|
||||||
|
ldr r1, =mode_svc
|
||||||
|
msr ELR_hyp, r1
|
||||||
|
msr SPSR_hyp, r0
|
||||||
|
eret
|
||||||
|
nop
|
||||||
|
|
||||||
|
mode_svc:
|
||||||
|
nop
|
||||||
|
ldr sp, =stack_top
|
||||||
|
|
||||||
|
/* In supervisor mode */
|
||||||
|
ldr r0, =msg_svcmode
|
||||||
|
bl puts
|
||||||
|
|
||||||
|
/* Move CPIO archive out of the way */
|
||||||
|
ldr r0, =0xA000000
|
||||||
|
ldr r1, =stack_top
|
||||||
|
mov r2, #0x2000000
|
||||||
|
bl memcpy
|
||||||
|
|
||||||
|
load_files:
|
||||||
|
ldr r0, =msg_extract
|
||||||
|
bl puts
|
||||||
|
/* Load kernel */
|
||||||
|
ldr r0, =0x0A000000
|
||||||
|
ldr r1, =0x00200000
|
||||||
|
bl load_file
|
||||||
|
/* Load module */
|
||||||
|
ldr r4, =0x02000000
|
||||||
|
ldr r5, =0x00800000
|
||||||
|
load_files_loop:
|
||||||
|
mov r1, r4
|
||||||
|
bl load_file
|
||||||
|
cmp r0, #0
|
||||||
|
beq final_preparations
|
||||||
|
add r4, r4, r5
|
||||||
|
b load_files_loop
|
||||||
|
final_preparations:
|
||||||
|
/* Set up args and jump */
|
||||||
|
ldr r0, =msg_launch
|
||||||
|
bl print
|
||||||
|
mov r0, #0x22
|
||||||
|
bl putc
|
||||||
|
ldr r0, =argv1
|
||||||
|
bl print
|
||||||
|
mov r0, #0x22
|
||||||
|
bl putc
|
||||||
|
ldr r0, =msg_empty
|
||||||
|
bl puts
|
||||||
|
mov r0, #2
|
||||||
|
ldr r1, =argv
|
||||||
|
b 0x00200000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load a file from CPIO archive.
|
||||||
|
* r0: address of CPIO archive
|
||||||
|
* r1: address to copy the file to
|
||||||
|
* Return: address of next entry, or 0 if loading failed
|
||||||
|
*/
|
||||||
|
load_file:
|
||||||
|
push {r4-r8,lr}
|
||||||
|
mov r4, r0
|
||||||
|
mov r5, r1
|
||||||
|
mov r6, r2
|
||||||
|
|
||||||
|
/* Check header : either 070701 or 070702 */
|
||||||
|
ldr r0, [r4]
|
||||||
|
ldr r1, =0x37303730
|
||||||
|
cmp r0, r1
|
||||||
|
bne load_file_failed
|
||||||
|
ldr r0, [r4, #4]
|
||||||
|
ldr r1, =0xFFFF
|
||||||
|
and r1, r1, r0
|
||||||
|
ldr r2, =0x3130
|
||||||
|
cmp r1, r2
|
||||||
|
beq load_file_header_ok
|
||||||
|
ldr r2, =0x3230
|
||||||
|
cmp r1, r2
|
||||||
|
bne load_file_failed
|
||||||
|
load_file_header_ok:
|
||||||
|
/* Check for trailer */
|
||||||
|
ldrh r0, [r4, #0x6e]
|
||||||
|
ldr r1, =0x5254
|
||||||
|
cmp r1, r0
|
||||||
|
beq load_file_failed
|
||||||
|
ldrh r0, [r4, #0x6e]
|
||||||
|
ldr r1, =0x4941
|
||||||
|
cmp r1, r0
|
||||||
|
beq load_file_failed
|
||||||
|
|
||||||
|
/* Get data size */
|
||||||
|
add r0, r4, #0x36
|
||||||
|
bl hex2bin
|
||||||
|
mov r7, r0
|
||||||
|
/* Get filename size */
|
||||||
|
add r0, r4, #0x5e
|
||||||
|
bl hex2bin
|
||||||
|
mov r8, r0
|
||||||
|
|
||||||
|
/* Print file, size and offset */
|
||||||
|
add r0, r4, #0x6e
|
||||||
|
bl print
|
||||||
|
|
||||||
|
mov r0, r8
|
||||||
|
load_file_name_padding_loop:
|
||||||
|
cmp r0, #24
|
||||||
|
bgt load_file_name_padding_loop_end
|
||||||
|
push {r0}
|
||||||
|
mov r0, #0x20
|
||||||
|
bl putc
|
||||||
|
pop {r0}
|
||||||
|
add r0, r0, #1
|
||||||
|
b load_file_name_padding_loop
|
||||||
|
|
||||||
|
load_file_name_padding_loop_end:
|
||||||
|
ldr r0, =msg_size
|
||||||
|
bl print
|
||||||
|
mov r0, r7
|
||||||
|
bl print_hex
|
||||||
|
ldr r0, =msg_addr
|
||||||
|
bl print
|
||||||
|
mov r0, r5
|
||||||
|
bl print_hex
|
||||||
|
/* Add CR/LF */
|
||||||
|
mov r0, #0xd
|
||||||
|
bl putc
|
||||||
|
mov r0, #0xa
|
||||||
|
bl putc
|
||||||
|
|
||||||
|
/* Get pointer to data source */
|
||||||
|
add r1, r4, #0x6e
|
||||||
|
add r1, r1, r8
|
||||||
|
/* Align to 4 bytes */
|
||||||
|
and r2, r1, #0x3
|
||||||
|
cmp r2, #0
|
||||||
|
mov r0, #4
|
||||||
|
subne r2, r0, r2
|
||||||
|
addne r1, r1, r2
|
||||||
|
|
||||||
|
mov r0, r5
|
||||||
|
mov r2, r7
|
||||||
|
push {r1}
|
||||||
|
bl memcpy
|
||||||
|
|
||||||
|
pop {r0}
|
||||||
|
add r0, r7
|
||||||
|
/* Align to 4 bytes */
|
||||||
|
and r2, r0, #0x3
|
||||||
|
cmp r2, #0
|
||||||
|
mov r1, #4
|
||||||
|
subne r2, r1, r2
|
||||||
|
addne r0, r0, r2
|
||||||
|
|
||||||
|
pop {r4-r8,lr}
|
||||||
|
bx lr
|
||||||
|
load_file_failed:
|
||||||
|
mov r0, #0
|
||||||
|
pop {r4-r8,lr}
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send one character to the PL011 UART.
|
||||||
|
* r0: character to send
|
||||||
|
*/
|
||||||
|
putc:
|
||||||
|
/* Loop as long as FIFO isn't empty */
|
||||||
|
ldr r1, =0x3f201018
|
||||||
|
ldr r1, [r1]
|
||||||
|
and r1, #0x80
|
||||||
|
tst r1, #0x80
|
||||||
|
beq putc
|
||||||
|
|
||||||
|
# Write character
|
||||||
|
ldr r1, =0x3f201000
|
||||||
|
str r0, [r1]
|
||||||
|
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print an ASCIIZ string to the PL011 UART.
|
||||||
|
* r0: address of string to print
|
||||||
|
*/
|
||||||
|
print:
|
||||||
|
push {lr}
|
||||||
|
/* If end of string, add newline */
|
||||||
|
print_loop:
|
||||||
|
ldrb r1, [r0]
|
||||||
|
cmp r1, #0
|
||||||
|
beq print_end
|
||||||
|
|
||||||
|
/* Send character */
|
||||||
|
push {r0}
|
||||||
|
mov r0, r1
|
||||||
|
bl putc
|
||||||
|
pop {r0}
|
||||||
|
/* Advance to next character */
|
||||||
|
add r0, r0, #1
|
||||||
|
b print_loop
|
||||||
|
|
||||||
|
print_end:
|
||||||
|
pop {lr}
|
||||||
|
bx lr
|
||||||
|
/*
|
||||||
|
* Print an ASCIIZ string to the PL011 UART, followed by CR/LF.
|
||||||
|
* r0: address of string to print
|
||||||
|
*/
|
||||||
|
puts:
|
||||||
|
push {lr}
|
||||||
|
bl print
|
||||||
|
|
||||||
|
/* Add CR/LF */
|
||||||
|
mov r0, #0xd
|
||||||
|
bl putc
|
||||||
|
mov r0, #0xa
|
||||||
|
bl putc
|
||||||
|
|
||||||
|
pop {lr}
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert 8 hexadecimal characters to binary.
|
||||||
|
* r0: address of string to convert
|
||||||
|
* Return: the converted value
|
||||||
|
*/
|
||||||
|
hex2bin:
|
||||||
|
mov r1, #0
|
||||||
|
mov r2, #0
|
||||||
|
hex2bin_loop:
|
||||||
|
ldrb r3, [r0, r2]
|
||||||
|
cmp r3, #0x40
|
||||||
|
sublt r3, r3, #0x30
|
||||||
|
blt hex2bin_add_digit
|
||||||
|
cmp r3, #0x60
|
||||||
|
sublt r3, r3, #0x37
|
||||||
|
blt hex2bin_add_digit
|
||||||
|
sub r3, r3, #0x57
|
||||||
|
hex2bin_add_digit:
|
||||||
|
lsl r1, r1, #4
|
||||||
|
add r1, r1, r3
|
||||||
|
add r2, r2, #1
|
||||||
|
cmp r2, #8
|
||||||
|
blt hex2bin_loop
|
||||||
|
mov r0, r1
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a value as hexadecimal.
|
||||||
|
* r0: value to print
|
||||||
|
*/
|
||||||
|
print_hex:
|
||||||
|
push {lr}
|
||||||
|
mov r1, #8
|
||||||
|
print_hex_loop:
|
||||||
|
cmp r1, #0
|
||||||
|
ble print_hex_end
|
||||||
|
|
||||||
|
lsr r2, r0, #28
|
||||||
|
cmp r2, #10
|
||||||
|
addlt r2, r2, #0x30
|
||||||
|
addge r2, r2, #0x37
|
||||||
|
|
||||||
|
push {r0-r2}
|
||||||
|
mov r0, r2
|
||||||
|
bl putc
|
||||||
|
pop {r0-r2}
|
||||||
|
|
||||||
|
sub r1, r1, #1
|
||||||
|
lsl r0, r0, #4
|
||||||
|
b print_hex_loop
|
||||||
|
print_hex_end:
|
||||||
|
pop {lr}
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quickly copy a memory area to another.
|
||||||
|
* r0: destination
|
||||||
|
* r1: source
|
||||||
|
* r2: length
|
||||||
|
*/
|
||||||
|
memcpy:
|
||||||
|
push {r5-r11}
|
||||||
|
add r2, r0, r2
|
||||||
|
memcpy_loop:
|
||||||
|
cmp r0, r2
|
||||||
|
bge memcpy_done
|
||||||
|
ldm r1!, {r3-r11}
|
||||||
|
stm r0!, {r3-r11}
|
||||||
|
b memcpy_loop
|
||||||
|
memcpy_done:
|
||||||
|
pop {r5-r11}
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
msg_empty:
|
||||||
|
.asciz ""
|
||||||
|
msg_banner:
|
||||||
|
.asciz "MINIX 3 unpacker for Raspberry Pi"
|
||||||
|
msg_svcmode:
|
||||||
|
.asciz "Current mode: supervisor"
|
||||||
|
msg_hypmode:
|
||||||
|
.asciz "Current mode: hypervisor. Switching to supervisor mode..."
|
||||||
|
msg_extract:
|
||||||
|
.asciz "Extracting modules..."
|
||||||
|
msg_launch:
|
||||||
|
.asciz "Jumping into kernel, argv[1]="
|
||||||
|
msg_size:
|
||||||
|
.asciz " size:0x"
|
||||||
|
msg_addr:
|
||||||
|
.asciz " address:0x"
|
||||||
Loading…
Reference in New Issue
Block a user