diff options
Diffstat (limited to 'rbutil/mkzenboot/dualboot')
-rw-r--r-- | rbutil/mkzenboot/dualboot/Makefile | 50 | ||||
-rw-r--r-- | rbutil/mkzenboot/dualboot/bin2c.c | 140 | ||||
-rw-r--r-- | rbutil/mkzenboot/dualboot/config.h | 22 | ||||
-rw-r--r-- | rbutil/mkzenboot/dualboot/dualboot.c | 134 | ||||
-rw-r--r-- | rbutil/mkzenboot/dualboot/dualboot.lds | 32 |
5 files changed, 378 insertions, 0 deletions
diff --git a/rbutil/mkzenboot/dualboot/Makefile b/rbutil/mkzenboot/dualboot/Makefile new file mode 100644 index 0000000000..cc8c604f6e --- /dev/null +++ b/rbutil/mkzenboot/dualboot/Makefile @@ -0,0 +1,50 @@ +CC=gcc +LD=ld +OC=objcopy +CROSS_PREFIX=arm-elf-eabi- +REGS_PATH=../../../firmware/target/arm/imx233/regs +CFLAGS=-mcpu=arm926ej-s -std=gnu99 -I. -I$(REGS_PATH) -nostdlib -ffreestanding -fomit-frame-pointer -O +LDFLAGS= +# Edit the following variables when adding a new target. +# mkimxboot.c also needs to be edited to refer to these +# To add a new target x you need to: +# 1) add x to the list in TARGETS +# 2) create a variable named OPT_x of the form: +# OPT_x=target specific defines +TARGETS=zenmozaic zenxfi zen +OPT_zenmozaic=-DCREATIVE_ZENMOZAIC -DIMX233_SUBTARGET=3700 +OPT_zenxfi=-DCREATIVE_ZENXFI -DIMX233_SUBTARGET=3700 +OPT_zen=-DCREATIVE_ZEN -DIMX233_SUBTARGET=3700 + +BOOTLDS=$(patsubst %, dualboot_%.lds, $(TARGETS)) +BOOTOBJS=$(patsubst %, dualboot_%.o, $(TARGETS)) +BOOTBINS=$(patsubst %, dualboot_%.arm-bin, $(TARGETS)) +BOOTELFS=$(patsubst %, dualboot_%.arm-elf, $(TARGETS)) + +all: ../dualboot.h ../dualboot.c $(BOOTELFS) + +# Dualboot bootloaders + +dualboot_%.o: dualboot.c + $(CROSS_PREFIX)$(CC) $(CFLAGS) $(OPT_$(@:dualboot_%.o=%)) -c -o $@ $^ + +dualboot_%.lds: dualboot.lds + $(CROSS_PREFIX)$(CC) $(CFLAGS) $(OPT_$(@:dualboot_%.lds=%)) -E -x c - < $< | sed '/#/d' > $@ + +dualboot_%.arm-elf: dualboot_%.o dualboot_%.lds + $(CROSS_PREFIX)$(LD) $(LDFLAGS) -T$(@:dualboot_%.arm-elf=dualboot_%.lds) -o $@ $< + +# Rules for the ARM code embedded in mkamsboot - assemble, link, then extract +# the binary code and finally convert to .h for building in mkamsboot + +%.arm-bin: %.arm-elf + $(CROSS_PREFIX)$(OC) -O binary $< $@ + +../dualboot.c ../dualboot.h: $(BOOTBINS) bin2c + ./bin2c ../dualboot $(BOOTBINS) + +bin2c: bin2c.c + $(CC) -o bin2c bin2c.c + +clean: + rm -f *~ bin2c $(BOOTBINS) $(BOOTOBJS) $(BOOTELFS) $(BOOTLDS) diff --git a/rbutil/mkzenboot/dualboot/bin2c.c b/rbutil/mkzenboot/dualboot/bin2c.c new file mode 100644 index 0000000000..b02af88a4d --- /dev/null +++ b/rbutil/mkzenboot/dualboot/bin2c.c @@ -0,0 +1,140 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 Dave Chapman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> +#include <libgen.h> + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +static off_t filesize(int fd) +{ + struct stat buf; + + fstat(fd,&buf); + return buf.st_size; +} + +static void write_cfile(const unsigned char* buf, off_t len, FILE* fp, const char *name) +{ + int i; + + fprintf(fp,"unsigned char %s[%ld] = {",name,len); + + for (i=0;i<len;i++) { + if ((i % 16) == 0) { + fprintf(fp,"\n "); + } + if (i == (len-1)) { + fprintf(fp,"0x%02x",buf[i]); + } else if ((i % 16) == 15) { + fprintf(fp,"0x%02x,",buf[i]); + } else { + fprintf(fp,"0x%02x, ",buf[i]); + } + } + fprintf(fp,"\n};\n"); +} + +int main (int argc, char* argv[]) +{ + char* cname; + int i; + FILE *cfile, *hfile; + char cfilename[256], hfilename[256]; + + if (argc < 3) { + fprintf(stderr,"Usage: bin2c cname file1 [file2 [file3 ...]]\n"); + return 1; + } + + cname=argv[1]; + + snprintf(cfilename,256,"%s.c",cname); + cfile = fopen(cfilename,"w+"); + if (cfile == NULL) { + fprintf(stderr,"Couldn't open %s\n",cfilename); + return 2; + } + + snprintf(hfilename,256,"%s.h",cname); + hfile = fopen(hfilename,"w+"); + if (hfile == NULL) { + fprintf(stderr,"Couldn't open %s\n",hfilename); + fclose(cfile); + return 3; + } + + fprintf(cfile,"/* Generated by bin2c */\n\n"); + fprintf(cfile,"#include \"%s\"\n\n", basename(hfilename)); + fprintf(hfile,"/* Generated by bin2c */\n\n"); + + for(i=0; i < argc - 2; i++) { + unsigned char* buf; + off_t len; + off_t orig_len; + char *ext; + char *array = argv[2+i]; + + int fd = open(array,O_RDONLY|O_BINARY); + if (fd < 0) { + fprintf(stderr,"Can not open %s\n",argv[2+i]); + fclose(cfile); + fclose(hfile); + return 4; + } + + orig_len = filesize(fd); + /* pad to 32bit */ + len = (orig_len + 3) & ~3; + + buf = malloc(len); + if (read(fd,buf,orig_len) < orig_len) { + fprintf(stderr,"Short read, aborting\n"); + return 5; + } + + /* pad to 32bit with zeros */ + if (len > orig_len) + memset(buf+orig_len, 0, len-orig_len); + + /* remove file extension */ + ext = strchr (array, '.'); + if (ext != NULL) + *ext = '\0'; + write_cfile (buf, len, cfile, array); + fprintf(hfile,"extern unsigned char %s[%ld];\n",array,len); + + close(fd); + } + + fclose(cfile); + fclose(hfile); + + return 0; +} diff --git a/rbutil/mkzenboot/dualboot/config.h b/rbutil/mkzenboot/dualboot/config.h new file mode 100644 index 0000000000..ff59cee710 --- /dev/null +++ b/rbutil/mkzenboot/dualboot/config.h @@ -0,0 +1,22 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2013 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +/** empty, used by register files */ diff --git a/rbutil/mkzenboot/dualboot/dualboot.c b/rbutil/mkzenboot/dualboot/dualboot.c new file mode 100644 index 0000000000..d0587fa65d --- /dev/null +++ b/rbutil/mkzenboot/dualboot/dualboot.c @@ -0,0 +1,134 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2013 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "regs-pinctrl.h" +#include "regs-power.h" +#include "regs-lradc.h" + +typedef unsigned long uint32_t; + +// target specific boot decision +enum boot_t +{ + BOOT_STOP, /* power down */ + BOOT_ROCK, /* boot to Rockbox */ + BOOT_OF, /* boot to OF */ +}; + +/** + * Helper functions + */ + +static inline int __attribute__((always_inline)) read_gpio(int bank, int pin) +{ + return (HW_PINCTRL_DINn(bank) >> pin) & 1; +} + +static inline int __attribute__((always_inline)) read_pswitch(void) +{ +#if IMX233_SUBTARGET >= 3700 + return BF_RD(POWER_STS, PSWITCH); +#else + return BF_RD(DIGCTL_STATUS, PSWITCH); +#endif +} + +/* only works for channels <=7, always divide by 2, never accumulates */ +static inline void __attribute__((always_inline)) setup_lradc(int src) +{ + BF_CLR(LRADC_CTRL0, SFTRST); + BF_CLR(LRADC_CTRL0, CLKGATE); + /* don't bother changing the source, we are early enough at boot so that + * channel x is mapped to source x */ + HW_LRADC_CHn_CLR(src) = BM_OR2(LRADC_CHn, NUM_SAMPLES, ACCUMULATE); + BF_SETV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << src); +} + +#define BP_LRADC_CTRL1_LRADCx_IRQ(x) (x) +#define BM_LRADC_CTRL1_LRADCx_IRQ(x) (1 << (x)) + +static inline int __attribute__((always_inline)) read_lradc(int src) +{ + BF_CLR(LRADC_CTRL1, LRADCx_IRQ(src)); + BF_SETV(LRADC_CTRL0, SCHEDULE, 1 << src); + while(!BF_RD(LRADC_CTRL1, LRADCx_IRQ(src))); + return BF_RDn(LRADC_CHn, src, VALUE); +} + +static inline void __attribute__((noreturn)) power_down() +{ + /* power down */ + HW_POWER_RESET = BM_OR2(POWER_RESET, UNLOCK, PWD); + while(1); +} + +/** + * Boot decision functions + */ + +#if defined(CREATIVE_ZENMOZAIC) || defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) +static enum boot_t boot_decision() +{ + setup_lradc(0); // setup LRADC channel 0 to read keys + /* make a decision */ + /* read keys */ + int val = read_lradc(0); + /* if back is pressed, boot to OF + * otherwise boot to RB */ + if(val >= 2650 && val < 2750) // conveniently, all players use the same value + return BOOT_OF; + return BOOT_ROCK; +} +#else +#warning You should define a target specific boot decision function +static int boot_decision() +{ + return BOOT_ROCK; +} +#endif + +static int main(uint32_t rb_addr, uint32_t of_addr) +{ + switch(boot_decision()) + { + case BOOT_ROCK: + return rb_addr; + case BOOT_OF: + /* fix back the loading address + /* NOTE: see mkzenboot for more details */ + *(uint32_t *)0x20 = of_addr; + return 0; + case BOOT_STOP: + default: + power_down(); + } +} + +/** Glue for the linker mostly */ + +extern uint32_t of_vector; +extern uint32_t rb_vector; +extern uint32_t boot_arg; + +void __attribute__((section(".start"))) start() +{ + uint32_t addr = main(rb_vector, of_vector); + ((void (*)(uint32_t))addr)(boot_arg); +} diff --git a/rbutil/mkzenboot/dualboot/dualboot.lds b/rbutil/mkzenboot/dualboot/dualboot.lds new file mode 100644 index 0000000000..7444a1e427 --- /dev/null +++ b/rbutil/mkzenboot/dualboot/dualboot.lds @@ -0,0 +1,32 @@ +ENTRY(start) +OUTPUT_FORMAT(elf32-littlearm) +OUTPUT_ARCH(arm) + +MEMORY +{ + /* keep this consistent with the address in mkzenboot.c */ +#if IMX233_SUBTARGET == 3700 + RAM : ORIGIN = 0x41000000, LENGTH = 0x8000 +#elif IMX233_SUBTARGET == 3600 + RAM : ORIGIN = 0x61000000, LENGTH = 0x8000 +#else +#error define me +#endif +} + +SECTIONS +{ + .text : + { + *(.start*) + *(.text*) + . = ALIGN(4); + LONG(0x1ceb00da) + of_vector = .; + . += 4; + rb_vector = .; + . += 4; + boot_arg = .; + . += 4; + } > RAM +} |