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:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,6 +9,7 @@ cscope.*
|
||||
*.rej
|
||||
*.[1-9].gz
|
||||
*.o
|
||||
*.elf
|
||||
*.[psS]o
|
||||
*.pico
|
||||
lib*.so*
|
||||
|
||||
@@ -3,7 +3,7 @@ set -e
|
||||
|
||||
exec >/dev/log
|
||||
exec 2>/dev/log
|
||||
exec </dev/null
|
||||
exec </dev/console
|
||||
|
||||
FSCK=/bin/fsck_mfs
|
||||
ACPI=/service/acpi
|
||||
@@ -45,6 +45,12 @@ then if [ -e $ACPI -a -n "`sysenv acpi`" ]
|
||||
/bin/umount /proc >/dev/null
|
||||
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 ]
|
||||
then echo Starting the mmc driver
|
||||
/bin/service -c up /service/mmc -dev /dev/c0d0
|
||||
@@ -88,7 +94,7 @@ fi
|
||||
|
||||
echo "Root device name is $rootdevname"
|
||||
|
||||
if ! sysenv cdproberoot >/dev/null
|
||||
if (! sysenv cdproberoot) && (! sysenv bootramdisk) >/dev/null
|
||||
then
|
||||
if [ -e $FSCK ]
|
||||
then $FSCK -p $rootdevname
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
#ifndef _INTERRUPT_H
|
||||
#define _INTERRUPT_H
|
||||
|
||||
#define NR_IRQ_VECTORS 125
|
||||
#define NR_IRQ_VECTORS 128
|
||||
|
||||
#endif /* _INTERRUPT_H */
|
||||
|
||||
@@ -67,12 +67,15 @@
|
||||
|
||||
#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_RPI MINIX_MK_BOARD_VENDOR(1<<2)
|
||||
|
||||
#define MINIX_BOARD_GENERIC MINIX_MK_BOARD(1<<0)
|
||||
/* BeagleBoard XM */
|
||||
#define MINIX_BOARD_BBXM MINIX_MK_BOARD(1<<1)
|
||||
/* BeagleBone (Black and* white) */
|
||||
#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 */
|
||||
#define MINIX_BOARD_VARIANT_GENERIC MINIX_MK_BOARD_VARIANT(1<<0)
|
||||
@@ -81,6 +84,10 @@
|
||||
/* BeagleBone Black */
|
||||
#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 \
|
||||
( MINIX_BOARD_ARCH_X86 \
|
||||
| MINIX_BOARD_ARCH_VARIANT_X86_GENERIC \
|
||||
@@ -113,6 +120,22 @@
|
||||
| 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) \
|
||||
( (BOARD_ID_BBXM & ~MINIX_BOARD_VARIANT_MASK) == (v & ~MINIX_BOARD_VARIANT_MASK))
|
||||
/* Either one of the known BeagleBones */
|
||||
@@ -121,6 +144,9 @@
|
||||
#define BOARD_IS_BBW(v) ( v == BOARD_ID_BBW)
|
||||
#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_MASK \
|
||||
(MINIX_BOARD_ARCH_MASK \
|
||||
@@ -148,6 +174,8 @@ static struct shortname2id shortname2id[] = {
|
||||
{.name = "BBXM",.id = BOARD_ID_BBXM},
|
||||
{.name = "A335BONE",.id = BOARD_ID_BBW},
|
||||
{.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
|
||||
@@ -162,6 +190,8 @@ static struct board_id2name board_id2name[] = {
|
||||
{.id = BOARD_ID_BBXM,.name = "ARM-ARMV7-TI-BBXM-GENERIC"},
|
||||
{.id = BOARD_ID_BBW,.name = "ARM-ARMV7-TI-BB-WHITE"},
|
||||
{.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
|
||||
|
||||
@@ -319,4 +319,9 @@
|
||||
#define CONTROL_CONF_PUDEN (1<<3)
|
||||
#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 */
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "bsp_timer.h"
|
||||
#include "bsp_intr.h"
|
||||
#include "cpufunc_timer.h"
|
||||
|
||||
static unsigned tsc_per_ms[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;
|
||||
} else if (BOARD_IS_BB(machine.board_id)) {
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
*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)
|
||||
|
||||
@@ -211,6 +211,11 @@ void setup_mbi(multiboot_info_t *mbi, char *bootargs)
|
||||
mb_mmap_start = 0x80000000;
|
||||
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
|
||||
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_BRANCH=minix}
|
||||
: ${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"
|
||||
Reference in New Issue
Block a user