Skip to content

Commit

Permalink
Fernly runs on MT6261
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Edison committed Apr 11, 2016
1 parent 0e7abd6 commit f21fd73
Show file tree
Hide file tree
Showing 12 changed files with 419 additions and 27 deletions.
26 changes: 25 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
include mkenv.mk
include magic.mk

# isogashii:
BUILD = build
CROSS_COMPILE=arm-none-eabi-

CFLAGS = -march=armv5te -mfloat-abi=soft -Wall \
-Os -ggdb -Iinclude -marm -fno-stack-protector
-Os -Iinclude -marm -fno-stack-protector
AFLAGS =

LDFLAGS = --nostdlib -T fernvale.ld
LIBS = lib/libgcc-armv5.a

STAGE1_LDFLAGS = --nostdlib -T stage1.ld

SRC_C = \
bionic.c \
cmd-hex.c \
Expand Down Expand Up @@ -42,7 +48,19 @@ SRC_S = \

OBJ = $(addprefix $(BUILD)/, $(SRC_S:.S=.o) $(SRC_C:.c=.o))

STAGE1_SRC_C = \
stage1.c \
serial.c \
vectors.c

STAGE1_SRC_S = \
start.S

STAGE1_OBJ = $(addprefix $(BUILD)/, $(STAGE1_SRC_S:.S=.o) $(STAGE1_SRC_C:.c=.o))

all: $(BUILD)/firmware.bin \
$(BUILD)/stage1.bin \
$(BUILD)/dump-rom-usb.bin \
$(BUILD)/usb-loader.bin \
$(BUILD)/mt6261-test.bin \
$(BUILD)/fernly-usb-loader
Expand All @@ -62,6 +80,12 @@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(BUILD)/firmware.elf: $(OBJ)
$(LD) $(LDFLAGS) --entry=reset_handler -o $@ $(OBJ) $(LIBS)

$(BUILD)/stage1.bin: $(BUILD)/stage1.elf
$(OBJCOPY) -S -O binary $(BUILD)/stage1.elf $@

$(BUILD)/stage1.elf: $(STAGE1_OBJ)
$(LD) $(STAGE1_LDFLAGS) --entry=reset_handler -o $@ $(STAGE1_OBJ) $(LIBS)

$(OBJ): $(HEADER_BUILD)/generated.h | $(OBJ_DIRS)
$(HEADER_BUILD)/generated.h: | $(HEADER_BUILD)
touch $@
Expand Down
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,43 @@ For example:
make CROSS_COMPILE=arm-none-linux-gnueabi-


Running on MT6261 devices
-------------------------

To run the Fernly shell on an MT6261 device, follow the instructions below
except that the command would be:

build/fernly-usb-loader -s /dev/fernvale build/stage1.bin build/firmware.bin

Stage1.bin uses Fernly's own USR serial I/O code instead of calling ROM
routines, allowing Fernly to load at address 0x70000000 at the bottom of
RAM. This is helpful-bordering-on-necessary because of the size of Fernly
and the smaller RAM capacity of the MT6261 compared to the 6260. The ROM
routines can't load this low because that area is used for their buffer
memory and program variables.

To capture the contents of ROM, run the command:

build/fernly-usb-loader /dev/fernvale build/dump-rom-usb.bin

Capture the output to a text file, edit out the diagnostic lines from
fernly-usb-loader, prepend the one line:

data = [

and append the six lines:

]

f = open('rom.bin','wb')
for s in data:
f.write(chr(int(s,16)))
f.close()

Save it as a file with a ".py" suffix and run it as a Python script.
It will save the binary rom image as the file "rom.bin".


Running Fernly
--------------

Expand Down
Binary file added build/dump-rom-usb.bin
Binary file not shown.
Binary file added build/firmware.bin
Binary file not shown.
92 changes: 92 additions & 0 deletions dump-rom-usb.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
.text

.global _start
_start:
disable_interrupts:
mrs r0, cpsr
mov r1, #0xc0
orr r0, r0, r1
msr cpsr_cxsf, r0

relocate_stack:
ldr r0, =0x70009ffc // stack_start
mov sp, r0

dump_memory:
bl output_newline

ldr r7, =0xfff00000 // start address
add r8, r7, #0x8800 // count
mov r5, #0

encode_hex_loop:
# hex encoding borrowed from gcc output:
ldrb r2, [r7], #1
mov r1, r2, lsr #4
add r1, r1, #48
and r2, r2, #15
add r2, r2, #48
cmp r1, #57
addhi r1, r1, #39
cmp r2, #57
addhi r2, r2, #39

adr r0, hex_msg
strb r1, [r0, #1]
strb r2, [r0, #2]
bl output_hex

add r5, r5, #1
tst r5, #15
bleq output_newline

cmp r7, r8
bne encode_hex_loop

bl output_banner

bl reboot
error:
b error

output_hex:
adr r0, hex_msg
mov r1, #6

b usb_out

output_banner:
adr r0, fake_banner
mov r1, #11

b usb_out

output_newline:
adr r0, newline_msg
mov r1, #1

usb_out:
push {lr}

# void usb_uart_write(char *data, int bytes, int timeout)
ldr r3, =0xfff00b7f
blx r3

# void usb_uart_flush(void)
ldr r3, =0xfff01cb1
blx r3

pop {lr}
bx lr

// trigger WDT reboot
reboot:
ldr r0, =0xa003001c
ldr r1, =0x1209
str r1, [r0]
bx lr // shouldn't get here

hex_msg: .asciz "\"xx\", "
newline_msg: .asciz "\n"
fake_banner: .asciz "# >"

60 changes: 45 additions & 15 deletions fernly-usb-loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#define STAGE_2_WRITE_SIZE 1
#define STAGE_3_WRITE_ALL_AT_ONCE 1 /* Write stage 3 in one write() */
#define STAGE_3_WRITE_SIZE 1
#define FERNLY_USB_LOADER_ADDR 0x7000a000
#define FERNLY_USB_LOADER_ADDR 0x70009000

#define ASSERT(x) do { if ((x)) exit(1); } while(0)

Expand Down Expand Up @@ -937,6 +937,8 @@ int fernvale_set_serial(int serfd) {
cfsetispeed(&t, BAUDRATE);
cfsetospeed(&t, BAUDRATE);
cfmakeraw(&t);
t.c_cc[VMIN] = 0;
t.c_cc[VTIME] = 100; // timeout in deciseconds.. that's 10 sec
ret = tcsetattr(serfd, TCSANOW, &t);
if (-1 == ret) {
perror("Failed to set attributes");
Expand All @@ -956,7 +958,9 @@ static int fernvale_wait_banner(int fd, const char *banner, int banner_size) {
int i;

while (1 == read(fd, &buf[offset], 1)) {


printf("%c", buf[offset]);

tst = (offset + 1) % sizeof(buf);

i = 0;
Expand Down Expand Up @@ -1459,12 +1463,14 @@ static void cmd_end_fmt(const char *fmt, ...) {

static void print_help(const char *name)
{
printf("Usage: %s [-l logfile] [-s] [serial port] "
printf("Usage: %s [-a address] [-l logfile] [-s] [serial port] "
"[stage 1 bootloader] "
"[[stage 2 bootloader]] "
"[payload]\n", name);
printf("\n");
printf("Arguments:\n");
printf(" -a [address] Set load address for stage 1 bootloader (default: 0x%x)\n",
FERNLY_USB_LOADER_ADDR);
printf(" -l [logfile] Log boot output to the specified file\n");
printf(" -w Wait for serial port to appear\n");
printf(" -s Enter boot shell\n");
Expand All @@ -1482,17 +1488,23 @@ static void print_help(const char *name)
}

int main(int argc, char **argv) {
int serfd, binfd, s1blfd, payloadfd = -1, logfd = -1;
int serfd, binfd = -1, s1blfd, payloadfd = -1, logfd = -1;
char *logname = NULL;
uint32_t ret;
int opt;
int shell = 0;
int wait_serial = 0;
int factory_test = 0;

while ((opt = getopt(argc, argv, "hl:swt")) != -1) {
uint32_t usb_loader_addr = FERNLY_USB_LOADER_ADDR;

while ((opt = getopt(argc, argv, "a:hl:swt")) != -1) {
switch(opt) {

case 'a':
usb_loader_addr = strtoul(optarg, NULL, 0);
break;

case 'l':
logname = strdup(optarg);
break;
Expand Down Expand Up @@ -1521,7 +1533,8 @@ int main(int argc, char **argv) {
argc -= (optind - 1);
argv += (optind - 1);

if ((argc != 4) && (argc != 5)) {
if ((argc != 3) && (argc != 4) && (argc != 5)) {
printf("%d is wrong # of args\n", argc);
exit(1);
}

Expand Down Expand Up @@ -1554,10 +1567,12 @@ int main(int argc, char **argv) {
exit(1);
}

binfd = open(argv[3], O_RDONLY);
if (-1 == binfd) {
perror("Unable to open firmware file");
exit(1);
if (argc == 4 || argc == 5) {
binfd = open(argv[3], O_RDONLY);
if (-1 == binfd) {
perror("Unable to open firmware file");
exit(1);
}
}

if (argc == 5) {
Expand Down Expand Up @@ -1681,20 +1696,30 @@ int main(int argc, char **argv) {
cmd_end_fmt("0x%04x", ret);

cmd_begin("Loading Fernly USB loader");
ASSERT(fernvale_cmd_send_fd(serfd, FERNLY_USB_LOADER_ADDR, s1blfd));
ASSERT(fernvale_cmd_send_fd(serfd, usb_loader_addr, s1blfd));
cmd_end();

cmd_begin("Executing Ferly USB loader");
ASSERT(fernvale_cmd_jump(serfd, FERNLY_USB_LOADER_ADDR));
ASSERT(fernvale_cmd_jump(serfd, usb_loader_addr));
cmd_end();

cmd_begin("Waiting for Fernly USB loader banner");
ASSERT(fernvale_wait_banner(serfd, ">", 1));
cmd_end();

cmd_begin("Writing stage 2");
ASSERT(fernvale_write_stage2(serfd, binfd));
cmd_end();
if (binfd == -1) {
close(serfd);
return 0;
}

// you can change this to "#if 0" during testing, at times when
// you don't expect or need Fernly USB loader to actually work
#if 1
if (binfd != -1) {
cmd_begin("Writing stage 2");
ASSERT(fernvale_write_stage2(serfd, binfd));
cmd_end();
}

if (factory_test) {
cmd_begin("Starting factory test");
Expand All @@ -1714,6 +1739,7 @@ int main(int argc, char **argv) {
}

if (shell) {
cmd_begin("Start Fernly shell");
uint8_t bfr;
int ret;
struct termios t;
Expand Down Expand Up @@ -1762,6 +1788,8 @@ int main(int argc, char **argv) {
if (FD_ISSET(STDIN_FILENO, &rfds)) {
if (1 != read(STDIN_FILENO, &bfr, sizeof(bfr)))
break;
if (bfr == 0x3)
break;
write(serfd, &bfr, sizeof(bfr));
}
}
Expand All @@ -1771,6 +1799,8 @@ int main(int argc, char **argv) {
fernvale_wait_banner(serfd, prompt, strlen(prompt));
cmd_end();
}
#endif

close(serfd);
return 0;
}
2 changes: 1 addition & 1 deletion fernvale.ld
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ SECTIONS
{
/* The OS entry point is here */

. = 0x70006000; /* bootloader will copy data to this address */
. = 0x70000000; /* bootloader will copy data to this address */
.text : {
_stext = ABSOLUTE(.);
KEEP(*(vectors))
Expand Down
Loading

0 comments on commit f21fd73

Please sign in to comment.