Skip to content

Commit

Permalink
Add Linux loader
Browse files Browse the repository at this point in the history
This privdes just enough firmware to load Linux. The loader is linked to
run from the aliased BRAM address.

It can load a raw kernel (vmlinux.bin) or a wrapper that embeds the
device tree (dtbImage.microwatt).

The printf comes from https://github.com/mpredfearn/simple-printf

 1. Build Linux for microwatt
  objcopy -O binary microwatt/vmlinux vmlinux.bin

 2. Build a dtb

 3. Set MW_DEBUG to point to a copy of mw_debug and type `make load` to
    load the loader into BRAM.

 4. Press 'RESET'

 5. Follow the instructions:

	Microwatt Loader (Jun  2 2020 21:31:16)

	Load binaries into SDRAM and select option to start:

	vmlinux.bin and dtb:
	 mw_debug -b jtag stop load vmlinux.bin load microwatt.dtb 1000000 start
	 press 'l' to start'

	dtbImage.microwatt:
	 mw_debug -b jtag stop load dtbImage.microwatt 500000 start
	 press 'w' to start'

If you want to test other software, such as MicroPython, you can also
load it to the start of SDRAM and the loader will jump to it with 'l'.

Signed-off-by: Joel Stanley <[email protected]>
  • Loading branch information
shenki committed Jun 2, 2020
1 parent 84ab28b commit f03fb5b
Show file tree
Hide file tree
Showing 7 changed files with 678 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@
*.cf
*.s
*_tb
*.swp
main_ram.bin
tests/*/*.bin
tests/*/*.hex
tests/*/*.elf
TAGS
tags
scripts/mw_debug/mw_debug
loader/loader.bin
loader/loader.hex
loader/loader.elf
loader/powerpc.lds
*.swn
*.swo
41 changes: 41 additions & 0 deletions loader/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
ARCH = $(shell uname -m)
ifneq ("$(ARCH)", "ppc64")
ifneq ("$(ARCH)", "ppc64le")
CROSS_COMPILE ?= powerpc64le-linux-gnu-
endif
endif

PYTHON3 ?= python3
MW_DEBUG ?= mw_debug
BRAM_ADDRESS ?= 0x80000000

CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy

CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple \
-mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector \
-mstrict-align -ffreestanding -fdata-sections -ffunction-sections \
-I../include
ASFLAGS = $(CFLAGS)
LDFLAGS = -T powerpc.lds --gc-sections

all: loader.hex

load: loader.bin
$(MW_DEBUG) -b jtag load $^ $(BRAM_ADDRESS)

%.lds : %.lds.S
$(CC) -I../include -P -E $< -o $@

loader.elf: loader.o head.o ../lib/console.o load.o printf.o | powerpc.lds
$(LD) $(LDFLAGS) -o $@ $^

loader.bin: loader.elf
$(OBJCOPY) -O binary $^ $@

loader.hex: loader.bin
$(PYTHON3) ../scripts/bin2hex.py $^ > $@

clean:
@rm -f *.o loader.elf loader.bin loader.hex powerpc.lds
109 changes: 109 additions & 0 deletions loader/head.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/* Copyright 2013-2014 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <microwatt_soc.h>

#define STACK_TOP (BRAM_BASE + 0x2000)

#define FIXUP_ENDIAN \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
b 191f; /* Skip trampoline if endian is good */ \
.long 0xa600607d; /* mfmsr r11 */ \
.long 0x01006b69; /* xori r11,r11,1 */ \
.long 0x05009f42; /* bcl 20,31,$+4 */ \
.long 0xa602487d; /* mflr r10 */ \
.long 0x14004a39; /* addi r10,r10,20 */ \
.long 0xa64b5a7d; /* mthsrr0 r10 */ \
.long 0xa64b7b7d; /* mthsrr1 r11 */ \
.long 0x2402004c; /* hrfid */ \
191:


/* Load an immediate 64-bit value into a register */
#define LOAD_IMM64(r, e) \
lis r,(e)@highest; \
ori r,r,(e)@higher; \
rldicr r,r, 32, 31; \
oris r,r, (e)@h; \
ori r,r, (e)@l;

.section ".head","ax"

/*
* Microwatt currently enters in LE mode at 0x0, so we don't need to
* do any endian fix ups>
*/
. = 0
.global _start
_start:
b boot_entry

/* QEMU enters at 0x10 */
. = 0x10
FIXUP_ENDIAN
b boot_entry

. = 0x100
FIXUP_ENDIAN
b boot_entry

.global boot_entry
boot_entry:
/* setup stack */
LOAD_IMM64(%r1, STACK_TOP - 0x100)
LOAD_IMM64(%r12, main)
mtctr %r12,
bctrl
b .

#define EXCEPTION(nr) \
.= nr ;\
b .

/* More exception stubs */
EXCEPTION(0x300)
EXCEPTION(0x380)
EXCEPTION(0x400)
EXCEPTION(0x480)
EXCEPTION(0x500)
EXCEPTION(0x600)
EXCEPTION(0x700)
EXCEPTION(0x800)
EXCEPTION(0x900)
EXCEPTION(0x980)
EXCEPTION(0xa00)
EXCEPTION(0xb00)
EXCEPTION(0xc00)
EXCEPTION(0xd00)
EXCEPTION(0xe00)
EXCEPTION(0xe20)
EXCEPTION(0xe40)
EXCEPTION(0xe60)
EXCEPTION(0xe80)
EXCEPTION(0xf00)
EXCEPTION(0xf20)
EXCEPTION(0xf40)
EXCEPTION(0xf60)
EXCEPTION(0xf80)
#if 0
EXCEPTION(0x1000)
EXCEPTION(0x1100)
EXCEPTION(0x1200)
EXCEPTION(0x1300)
EXCEPTION(0x1400)
EXCEPTION(0x1500)
EXCEPTION(0x1600)
#endif
26 changes: 26 additions & 0 deletions loader/load.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Set up system for jumping to Linux.
*
* load_linux(kernel, dtb)
*/
.global load_linux
load_linux:
/* ABI:
* r5: zero (no openfirmware)
* r3: device tree
*/
addi %r5,0,0
addi %r12,%r3,0
addi %r3,%r4,0
mtctr %r12
bctrl
b .

/*
* Invalidate the icache.
*/
.global invalidate_icache
invalidate_icache:
icbi 0,0
isync
blr
63 changes: 63 additions & 0 deletions loader/loader.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include <stdint.h>
#include <stdbool.h>
#include <io.h>
#include <microwatt_soc.h>

#include "console.h"

extern void load_linux(unsigned long kernel, unsigned long dtb);
extern void invalidate_icache(void);

extern int simple_printf(char *fmt, ...);
#define printf(...) simple_printf(__VA_ARGS__)

#define DTB_ADDR 0x01000000L

#define DTBIMAGE_ADDR 0x500000L

int main(void)
{
int i;
potato_uart_init();
unsigned long kernel, dtb;

printf("\r\nMicrowatt Loader (%s %s)\r\n\r\n", __DATE__, __TIME__);

writeq(SYS_REG_CTRL_DRAM_AT_0, SYSCON_BASE + SYS_REG_CTRL);
invalidate_icache();

printf("Load binaries into SDRAM and select option to start:\r\n\r\n");
printf("vmlinux.bin and dtb:\r\n");
printf(" mw_debug -b jtag stop load vmlinux.bin load microwatt.dtb %x start\r\n",
DTB_ADDR);
printf(" press 'l' to start'\r\n\r\n");

printf("dtbImage.microwatt:\r\n");
printf(" mw_debug -b jtag stop load dtbImage.microwatt %x start\r\n",
DTBIMAGE_ADDR);
printf(" press 'w' to start'\r\n\r\n");

while (1) {
switch (getchar()) {
case 'l':
kernel = 0;
dtb = DTB_ADDR;
goto load;
case 'w':
kernel = DTBIMAGE_ADDR;
dtb = -1;
goto load;
default:
continue;
}
}

load:
printf("Loading Linux at %08x...\r\n", 0x0);
for (i = 0; i < 80; i++)
putchar('.');
printf("\r\n");
load_linux(kernel, dtb);

while (1);
}
17 changes: 17 additions & 0 deletions loader/powerpc.lds.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <microwatt_soc.h>

#define BASE_ADDR BRAM_BASE

SECTIONS
{
_start = .;
. = BASE_ADDR;
.head : {
KEEP(*(.head))
}
. = (BASE_ADDR + 0x1000);
.text : { *(.text) }
. = (BASE_ADDR + 0x2000);
.data : { *(.data) }
.bss : { *(.bss) }
}
Loading

0 comments on commit f03fb5b

Please sign in to comment.