fernly: More blocks discovered

This commit is contained in:
Sean Cross 2014-06-13 17:00:11 +08:00
parent 685824f56e
commit 9470228966
11 changed files with 1385 additions and 41 deletions

View file

@ -10,7 +10,9 @@ LIBS =
SRC_C = \ SRC_C = \
main.c \ main.c \
vectors.c \ vectors.c \
serial.c serial.c \
utils.c \
bionic.c
SRC_S = \ SRC_S = \
start.S start.S

125
README.md
View file

@ -17,3 +17,128 @@ To install, use radare2:
[0x00000000]> s 0x3460 [0x00000000]> s 0x3460
[0x00003460]> wf .//build/firmware.bin [0x00003460]> wf .//build/firmware.bin
Chip notes
----------
The chip memory-maps SPI at offset 0x10000000.
Memory Map
----------
+------------+------------+------------+-------------------------------------+
| 0x00000000 | 0x0fffffff | 0x0fffffff | PSRAM map, repeated and mirrored |
| | | | at 0x00800000 offsets |
+------------+------------+------------+-------------------------------------+
| 0x10000000 | 0x1fffffff | 0x0fffffff | Memory-mapped SPI chip |
+------------+------------+------------+-------------------------------------+
| ?????????? | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0x70000000 | 0x7000ffff | 0xffff | On-chip SRAM (maybe cache?) |
+------------+------------+------------+-------------------------------------+
| ?????????? | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0x80000000 | 0x80000008 | 0x08 | Config block (chip version, etc.) |
+------------+------------+------------+-------------------------------------+
| 0xa0000000 | 0xa0000008 | 0x08 | Config block (mirror?) |
+------------+------------+------------+-------------------------------------+
| 0xa0010000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0020000 | 0xa0020e10 | 0x0e10 | GPIO control block |
+------------+------------+------------+-------------------------------------+
| 0xa0030000 | 0xa0030040 | 0x40 | WDT block |
+------------+------------+------------+-------------------------------------+
| 0xa0050000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0060000 | ?????????? | ?????????? | ?? Possible IRQs at 0xa0060200 ???? |
+------------+------------+------------+-------------------------------------+
| 0xa0070000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0080000 | 0xa008005c | 0x5c | UART1 block |
+------------+------------+------------+-------------------------------------+
| 0xa0090000 | 0xa009005c | 0x5c | UART2 block |
+------------+------------+------------+-------------------------------------+
| 0xa00b0000 | 0xa00b006c | 0x6c | Bluetooth interface block |
+------------+------------+------------+-------------------------------------+
| 0xa00c0000 | 0xa00c002c | 0x2c | General purpose timer block |
+------------+------------+------------+-------------------------------------+
| 0xa00d0000 | 0xa00d0024 | 0x24 | Keypad scanner block |
+------------+------------+------------+-------------------------------------+
| 0xa00e0000 | 0xa00e0008 | 0x0c | PWM1 block |
+------------+------------+------------+-------------------------------------+
| 0xa00f0000 | 0xa00f00b0 | 0xb0 | SIM1 interface block |
+------------+------------+------------+-------------------------------------+
| 0xa0100000 | 0xa01000b0 | 0xb0 | SIM2 interface block |
+------------+------------+------------+-------------------------------------+
| 0xa0110000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0120000 | 0xa0120074 | 0x74 | I2C block |
+------------+------------+------------+-------------------------------------+
| 0xa0130000 | 0xa0130098 | 0x98 | SD1 block |
+------------+------------+------------+-------------------------------------+
| 0xa0140000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0160000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0170000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0180000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0190000 | 0xa0190310 | 0x58 | HIF (DMA) interface block |
+------------+------------+------------+-------------------------------------+
| 0xa01b0000 | 0xa01b0058 | 0x58 | NLI (arbiter) interface block |
+------------+------------+------------+-------------------------------------+
| 0xa01c0000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa01e0000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa01f0000 | 0xa01f0060 | 0x60 | OS timer block |
+------------+------------+------------+-------------------------------------+
| 0xa0220000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0240000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0260000 | 0xa0260058 | 0x58 | FSPI (internal FM radio) block |
+------------+------------+------------+-------------------------------------+
| 0xa0270000 | 0xa0270098 | 0x98 | SD2 block |
+------------+------------+------------+-------------------------------------+
| 0xa0410000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0420000 | 0xa04201d8 | 0x01d8 | CAM interface block |
+------------+------------+------------+-------------------------------------+
| 0xa0430000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0440000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0450000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0460000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0480000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0500000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0510000 | ?????????? | ?????????? | (03 00 00 00 repeated) ???????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0520000 | ?????????? | ?????????? | (contains 0xff at 0ffset 0x2c) ???? |
+------------+------------+------------+-------------------------------------+
| 0xa0530000 | ?????????? | ?????????? | (contains smattering of bits) ????? |
+------------+------------+------------+-------------------------------------+
| 0xa0540000 | ?????????? | ?????????? | (contains smattering of bits) ????? |
+------------+------------+------------+-------------------------------------+
| 0xa0710000 | 0xa0710078 | 0x78 | RTC block |
+------------+------------+------------+-------------------------------------+
| 0xa0720000 | ?????????? | ?????????? | ??????????????????????????????????? |
+------------+------------+------------+-------------------------------------+
| 0xa0730104 | 0xa073104c | ?????? | GPIO mode / pull control blocks |
+------------+------------+------------+-------------------------------------+
| 0xa074000c | 0xa0740014 | 0x0c | PWM2 block |
+------------+------------+------------+-------------------------------------+
| 0xa0740018 | 0xa0740020 | 0x0c | PWM3 block |
+------------+------------+------------+-------------------------------------+
| 0xa0750000 | 0xa075005c | 0x5c | ADCDET block |
+------------+------------+------------+-------------------------------------+
| 0xa0790000 | 0xa07900d8 | 0xd8 | ADC block |
+------------+------------+------------+-------------------------------------+
| 0xa0900000 | 0xa0900240 | 0x33 | USB block |
+------------+------------+------------+-------------------------------------+

663
bionic.c Normal file
View file

@ -0,0 +1,663 @@
/* $OpenBSD: strcasecmp.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* These functions were taken from libbionic. They replace GNU functions
* that weren't getting correctly linked.
*/
#include <stdint.h>
#include <string.h>
#include "bionic.h"
typedef unsigned char u_char;
/*
* This array is designed for mapping upper and lower case letter
* together for a case independent comparison. The mappings are
* based upon ascii character sequences.
*/
static const u_char charmap[] = {
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
};
/*
* Span the string s2 (skip characters that are in s2).
*/
size_t _strspn(const char *s1, const char *s2)
{
const char *p = s1, *spanp;
char c, sc;
/*
* Skip any characters in s2, excluding the terminating \0.
*/
cont:
c = *p++;
for (spanp = s2; (sc = *spanp++) != 0;)
if (sc == c)
goto cont;
return (p - 1 - s1);
}
/*
* Find the first occurrence in s1 of a character in s2 (excluding NUL).
*/
char * _strpbrk(const char *s1, const char *s2)
{
const char *scanp;
int c, sc;
while ((c = *s1++) != 0) {
for (scanp = s2; (sc = *scanp++) != 0;)
if (sc == c)
return ((char *)(s1 - 1));
}
return (NULL);
}
char *_strtok(char *str, const char *delim, char **saveptr) {
char *token;
if (str)
*saveptr = str;
token = *saveptr;
if (!token)
return NULL;
token += _strspn(token, delim);
*saveptr = _strpbrk(token, delim);
if (*saveptr)
*(*saveptr)++ = '\0';
return *token ? token : NULL;
}
int _strcasecmp(const char *s1, const char *s2)
{
const u_char *cm = charmap;
const u_char *us1 = (const u_char *)s1;
const u_char *us2 = (const u_char *)s2;
while (cm[*us1] == cm[*us2++])
if (*us1++ == '\0')
return (0);
return (cm[*us1] - cm[*--us2]);
}
/*
* sizeof(word) MUST BE A POWER OF TWO
* SO THAT wmask BELOW IS ALL ONES
*/
typedef long word; /* "word" used for optimal copy speed */
#define wsize sizeof(word)
#define wmask (wsize - 1)
#define MEMCOPY
/*
* Copy a block of memory, handling overlap.
* This is the routine that actually implements
* (the portable versions of) bcopy, memcpy, and memmove.
*/
#ifdef MEMCOPY
void *
_memcpy(void *dst0, const void *src0, size_t length)
#else
#ifdef MEMMOVE
void *
_memmove(void *dst0, const void *src0, size_t length)
#else
void
_bcopy(const void *src0, void *dst0, size_t length)
#endif
#endif
{
char *dst = dst0;
const char *src = src0;
size_t t;
if (length == 0 || dst == src) /* nothing to do */
goto done;
/*
* Macros: loop-t-times; and loop-t-times, t>0
*/
#define TLOOP(s) if (t) TLOOP1(s)
#define TLOOP1(s) do { s; } while (--t)
if ((unsigned long)dst < (unsigned long)src) {
/*
* Copy forward.
*/
t = (long)src; /* only need low bits */
if ((t | (long)dst) & wmask) {
/*
* Try to align operands. This cannot be done
* unless the low bits match.
*/
if ((t ^ (long)dst) & wmask || length < wsize)
t = length;
else
t = wsize - (t & wmask);
length -= t;
TLOOP1(*dst++ = *src++);
}
/*
* Copy whole words, then mop up any trailing bytes.
*/
t = length / wsize;
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
t = length & wmask;
TLOOP(*dst++ = *src++);
} else {
/*
* Copy backwards. Otherwise essentially the same.
* Alignment works as before, except that it takes
* (t&wmask) bytes to align, not wsize-(t&wmask).
*/
src += length;
dst += length;
t = (long)src;
if ((t | (long)dst) & wmask) {
if ((t ^ (long)dst) & wmask || length <= wsize)
t = length;
else
t &= wmask;
length -= t;
TLOOP1(*--dst = *--src);
}
t = length / wsize;
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
t = length & wmask;
TLOOP(*--dst = *--src);
}
done:
#if defined(MEMCOPY) || defined(MEMMOVE)
return (dst0);
#else
return;
#endif
}
static int _isspace(char c) {
return (c == ' '
|| c == '\f'
|| c == '\n'
|| c == '\r'
|| c == '\t'
|| c == '\v');
}
static int _isdigit(char c) {
return (c >= '0' && c <= '9');
}
static int _isupper(char c) {
return (c >= 'A' && c <= 'Z');
}
static int _islower(char c) {
return (c >= 'a' && c <= 'z');
}
static int _isalpha(char c) {
return _isupper(c) || _islower(c);
}
static int get_cuts(int base, unsigned long *cutoff, int *cutlim)
{
switch(base) {
case 1:
*cutoff = 4294967295;
*cutlim = 0;
break;
case 2:
*cutoff = 2147483647;
*cutlim = 1;
break;
case 3:
*cutoff = 1431655765;
*cutlim = 0;
break;
case 4:
*cutoff = 1073741823;
*cutlim = 3;
break;
case 5:
*cutoff = 858993459;
*cutlim = 0;
break;
case 6:
*cutoff = 715827882;
*cutlim = 3;
break;
case 7:
*cutoff = 613566756;
*cutlim = 3;
break;
case 8:
*cutoff = 536870911;
*cutlim = 7;
break;
case 9:
*cutoff = 477218588;
*cutlim = 3;
break;
case 10:
*cutoff = 429496729;
*cutlim = 5;
break;
case 11:
*cutoff = 390451572;
*cutlim = 3;
break;
case 12:
*cutoff = 357913941;
*cutlim = 3;
break;
case 13:
*cutoff = 330382099;
*cutlim = 8;
break;
case 14:
*cutoff = 306783378;
*cutlim = 3;
break;
case 15:
*cutoff = 286331153;
*cutlim = 0;
break;
case 16:
*cutoff = 268435455;
*cutlim = 15;
break;
case 17:
*cutoff = 252645135;
*cutlim = 0;
break;
case 18:
*cutoff = 238609294;
*cutlim = 3;
break;
case 19:
*cutoff = 226050910;
*cutlim = 5;
break;
case 20:
*cutoff = 214748364;
*cutlim = 15;
break;
case 21:
*cutoff = 204522252;
*cutlim = 3;
break;
case 22:
*cutoff = 195225786;
*cutlim = 3;
break;
case 23:
*cutoff = 186737708;
*cutlim = 11;
break;
case 24:
*cutoff = 178956970;
*cutlim = 15;
break;
case 25:
*cutoff = 171798691;
*cutlim = 20;
break;
case 26:
*cutoff = 165191049;
*cutlim = 21;
break;
case 27:
*cutoff = 159072862;
*cutlim = 21;
break;
case 28:
*cutoff = 153391689;
*cutlim = 3;
break;
case 29:
*cutoff = 148102320;
*cutlim = 15;
break;
case 30:
*cutoff = 143165576;
*cutlim = 15;
break;
case 31:
*cutoff = 138547332;
*cutlim = 3;
break;
case 32:
*cutoff = 134217727;
*cutlim = 31;
break;
case 33:
*cutoff = 130150524;
*cutlim = 3;
break;
case 34:
*cutoff = 126322567;
*cutlim = 17;
break;
case 35:
*cutoff = 122713351;
*cutlim = 10;
break;
case 36:
*cutoff = 119304647;
*cutlim = 3;
break;
case 37:
*cutoff = 116080197;
*cutlim = 6;
break;
case 38:
*cutoff = 113025455;
*cutlim = 5;
break;
case 39:
*cutoff = 110127366;
*cutlim = 21;
break;
case 40:
*cutoff = 107374182;
*cutlim = 15;
break;
case 41:
*cutoff = 104755299;
*cutlim = 36;
break;
case 42:
*cutoff = 102261126;
*cutlim = 3;
break;
case 43:
*cutoff = 99882960;
*cutlim = 15;
break;
case 44:
*cutoff = 97612893;
*cutlim = 3;
break;
case 45:
*cutoff = 95443717;
*cutlim = 30;
break;
case 46:
*cutoff = 93368854;
*cutlim = 11;
break;
case 47:
*cutoff = 91382282;
*cutlim = 41;
break;
case 48:
*cutoff = 89478485;
*cutlim = 15;
break;
case 49:
*cutoff = 87652393;
*cutlim = 38;
break;
case 50:
*cutoff = 85899345;
*cutlim = 45;
break;
case 51:
*cutoff = 84215045;
*cutlim = 0;
break;
case 52:
*cutoff = 82595524;
*cutlim = 47;
break;
case 53:
*cutoff = 81037118;
*cutlim = 41;
break;
case 54:
*cutoff = 79536431;
*cutlim = 21;
break;
case 55:
*cutoff = 78090314;
*cutlim = 25;
break;
case 56:
*cutoff = 76695844;
*cutlim = 31;
break;
case 57:
*cutoff = 75350303;
*cutlim = 24;
break;
case 58:
*cutoff = 74051160;
*cutlim = 15;
break;
case 59:
*cutoff = 72796055;
*cutlim = 50;
break;
case 60:
*cutoff = 71582788;
*cutlim = 15;
break;
case 61:
*cutoff = 70409299;
*cutlim = 56;
break;
case 62:
*cutoff = 69273666;
*cutlim = 3;
break;
case 63:
*cutoff = 68174084;
*cutlim = 3;
break;
case 64:
*cutoff = 67108863;
*cutlim = 63;
break;
default:
break;
}
return 0;
}
unsigned long _strtoul(const void *nptr, void **endptr, int base)
{
const char *s;
unsigned long acc, cutoff;
int c;
int neg, any, cutlim;
/*
* See strtol for comments as to the logic used.
*/
s = nptr;
do {
c = (unsigned char) *s++;
} while (_isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
get_cuts(base, &cutoff, &cutlim);
for (acc = 0, any = 0;; c = (unsigned char) *s++) {
if (_isdigit(c))
c -= '0';
else if (_isalpha(c))
c -= _isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0)
continue;
if (acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
acc = ULONG_MAX;
//errno = ERANGE;
} else {
any = 1;
acc *= (unsigned long)base;
acc += c;
}
}
if (neg && any > 0)
acc = -acc;
if (endptr != 0)
*(char **)endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
void _memset(void *dst0, char val, size_t length)
{
uint8_t *ptr = dst0;
while(length--)
*ptr++ = val;
}

11
include/bionic.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef __BIONIC_H__
#define __BIONIC_H__
# define ULONG_MAX 4294967295UL
size_t _strspn(const char *s1, const char *s2);
char * _strpbrk(const char *s1, const char *s2);
char *_strtok(char *str, const char *delim, char **saveptr);
int _strcasecmp(const char *s1, const char *s2);
void *_memcpy(void *dst0, const void *src0, size_t length);
void _memset(void *dst0, char val, size_t length);
unsigned long _strtoul(const void *nptr, void **endptr, int base);
#endif /* __BIONIC_H__ */

View file

@ -1,9 +1,15 @@
#ifndef __UART_H__ #ifndef __SERIAL_H__
#define __UART_H__ #define __SERIAL_H__
#include <stdint.h> #include <stdint.h>
int uart_putc(uint8_t c); int serial_putc(uint8_t c);
int uart_puts(char *s); int serial_puts(void *s);
void serial_puth(uint32_t hex, int digits); /* Put hex */
#endif /* __UART_H__ */ uint8_t serial_getc(void);
void serial_init(void);
int serial_print_hex(void *bfr, int count);
#endif /* __SERIAL_H__ */

5
include/utils.h Normal file
View file

@ -0,0 +1,5 @@
#ifndef __UTILS_H__
#define __UTILS_H__
#include <stdint.h>
#endif /* __UTILS_H__ */

376
main.c
View file

@ -1,10 +1,374 @@
#include <string.h>
#include "serial.h" #include "serial.h"
#include "utils.h"
#include "bionic.h"
#define PROMPT "fernly> "
static int serial_get_line(uint8_t *bfr, int len)
{
int cur = 0;
while (cur < len) {
bfr[cur] = serial_getc();
serial_putc(bfr[cur]);
/* Carriage Return */
if (bfr[cur] == '\n') {
bfr[cur] = '\0';
return 0;
}
/* Linefeed */
else if (bfr[cur] == '\r') {
bfr[cur] = '\0';
return 0;
}
/* Backspace */
else if (bfr[cur] == 0x7f) {
bfr[cur] = '\0';
if (cur > 0) {
serial_putc('\b');
serial_putc(' ');
serial_putc('\b');
cur--;
}
}
/* Ctrl-U */
else if (bfr[cur] == 0x15) {
while (cur > 0) {
serial_putc('\b');
serial_putc(' ');
serial_putc('\b');
bfr[cur] = '\0';
cur--;
}
}
/* Ctrl-W */
else if (bfr[cur] == 0x17) {
while (cur > 0 && bfr[cur] != ' ') {
serial_putc('\b');
serial_putc(' ');
serial_putc('\b');
bfr[cur] = '\0';
cur--;
}
}
/* Escape code */
else if (bfr[cur] == 0x1b) {
/* Next two characters are escape codes */
uint8_t next = serial_getc();
/* Sanity check: next should be '[' */
next = serial_getc();
}
else
cur++;
}
bfr[len - 1] = '\0';
return -1;
}
static void writew(uint16_t value, uint32_t addr)
{
*((volatile uint16_t *)addr) = value;
}
static uint16_t readw(uint32_t addr)
{
return *(volatile uint16_t *)addr;
}
static void writel(uint32_t value, uint32_t addr)
{
*((volatile uint32_t *)addr) = value;
}
static uint32_t readl(uint32_t addr)
{
return *(volatile uint32_t *)addr;
}
static int memory_test(uint32_t start, uint32_t length)
{
int addr;
register uint32_t val = 0xdeadbeef;
register uint32_t test;
uint32_t end = start + length;
serial_puts("Testing memory from ");
serial_puth(start, 8);
serial_puts(" to ");
serial_puth(end, 8);
serial_puts("");
for (addr = start; addr < end; addr += 4) {
if (! (addr & 0xffff)) {
serial_puts("\nAddress ");
serial_puth(addr, 8);
serial_puts("...");
}
writel(val, addr);
test = readl(addr);
if (test != val) {
serial_puts("Address ");
serial_puth(addr, 8);
serial_puts(" appears to be invalid! Expected 0xdeadbeef, got 0x");
serial_puth(test, 8);
serial_puts("\n");
}
}
return 0;
}
static int wdt_kick(void)
{
writel(0x1971, 0xa0030008);
return 0;
}
static int memory_search(uint32_t start, uint32_t length, uint32_t nonce, uint32_t mask)
{
int addr;
register uint32_t test;
uint32_t end = start + length;
serial_puts("Looking in memory from ");
serial_puth(start, 8);
serial_puts(" to ");
serial_puth(end, 8);
serial_puts(" for nonce ");
serial_puth(nonce, 8);
serial_puts("\n");
for (addr = start; addr < end; addr += 0x800) {
// if (! (addr & 0xffff)) {
serial_puts("\rAddress ");
serial_puth(addr, 8);
serial_puts("...");
wdt_kick();
// }
test = readw(addr);
if ((test & mask) == nonce) {
serial_puts(" ");
serial_puth(addr, 8);
serial_puts(" matches nonce\n");
}
}
return 0;
}
static int list_registers(void)
{
int var;
serial_puts("Registers:\n");
serial_puts("CPSR: ");
asm volatile ("mrs %0, cpsr":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("SPSR: ");
asm volatile ("mrs %0, spsr":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R0: ");
asm volatile ("mov %0, r0":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R1: ");
asm volatile ("mov %0, r1":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R2: ");
asm volatile ("mov %0, r2":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R3: ");
asm volatile ("mov %0, r3":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R4: ");
asm volatile ("mov %0, r4":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R5: ");
asm volatile ("mov %0, r5":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R6: ");
asm volatile ("mov %0, r6":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R7: ");
asm volatile ("mov %0, r7":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R8: ");
asm volatile ("mov %0, r8":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R9: ");
asm volatile ("mov %0, r9":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R10: ");
asm volatile ("mov %0, r10":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("FP: ");
asm volatile ("mov %0, r11":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("IP: ");
asm volatile ("mov %0, r12":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("SP: ");
asm volatile ("mov %0, r13":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R14: ");
asm volatile ("mov %0, r14":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("R15: ");
asm volatile ("mov %0, r15":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
serial_puts("LR: ");
asm volatile ("mov %0, lr":"=r" (var));
serial_puth(var, 8);
serial_puts("\n");
return 0;
}
static int read_address(uint8_t *arg)
{
uint32_t addr = _strtoul(arg, 0, 16);
serial_puth(addr, 16);
serial_puts(": ");
serial_puth(readl(addr), 16);
serial_puts("\n");
return 0;
}
static int write_address(uint8_t *arg)
{
uint8_t *valpos;
uint32_t val;
uint32_t addr = _strtoul(arg, (void **)&valpos, 16);
val = _strtoul(valpos, 0, 16);
serial_puth(addr, 16);
serial_puts(": ");
serial_puth(val, 16);
serial_puts("\n");
writel(val, addr);
return 0;
}
static int hex_print(uint8_t *arg)
{
uint32_t *addr = (uint32_t *)_strtoul(arg, 0, 16);
uint32_t data[1024];
int i;
for (i = 0; i < ((sizeof(data) / sizeof(*data))); i++)
data[i] = addr[i];
serial_puth((uint32_t)addr, 8);
serial_puts(":\n");
serial_print_hex(data, sizeof(data));
serial_puts("\n");
return 0;
}
int main(int argc, char **argv)
{
serial_init();
serial_puts("\n\nFernly shell\n");
while (1) {
uint8_t line[256];
serial_puts(PROMPT);
serial_get_line(line, sizeof(line));
serial_puts("\n");
switch(*line) {
case ' ':
case '\0':
break;
case 'm':
/* 0x70000000 - 0x7000ffff -> Stack, OCRAM? */
memory_test(0x0ffe0000, 0x40000000);
break;
case 's':
memory_search(0xa0000020, 0x2f000000,
// (0x2f << 24) | (0x2e << 16) |
// (0x2d << 8) | (0x2c << 0),
// (0x0b << 24) | (0x0a << 16) |
// (0x09 << 8) | (0x08 << 0),
0x00000401,
0x0000ffff);
break;
case 'h':
hex_print(line + 1);
break;
case 'l':
list_registers();
break;
case 'r':
read_address(line + 1);
break;
case 'w':
write_address(line + 1);
break;
case 'd':
serial_puts("Kicking WDT...\n");
wdt_kick();
break;
default:
serial_puts("Unknown command\n");
break;
}
}
int main(int argc, char **argv) {
while(1) {
int i;
uart_puts("Hello, world!\n");
for (i = 0; i < 0xf000; i++);
}
return 0; return 0;
} }

143
serial.c
View file

@ -1,20 +1,143 @@
#include <stdint.h> #include <stdint.h>
#include "serial.h" #include "serial.h"
int uart_putc(uint8_t c) {
uint32_t *uart_ldr = (uint32_t *)0xa0080014; #define UART_IS_DLL 0x100
uint32_t *uart_sbr = (uint32_t *)0xa0080000; #define UART_IS_LCR 0x200
#define UART_RBR 0x00
#define UART_THR 0x00
#define UART_IER 0x04
#define UART_IIR 0x08
#define UART_FCR 0x08
#define UART_LCR 0x0c
#define UART_MCR 0x10
#define UART_LSR 0x14
#define UART_MSR 0x18
#define UART_SCR 0x1c
#define UART_SPEED 0x24
/* The following are active when LCR[7] = 1 */
#define UART_DLL 0x100
#define UART_DLH 0x104
/* The following are active when LCR = 0xbf */
#define UART_EFR 0x208
#define UART_XON1 0x210
#define UART_XON2 0x214
#define UART_XOFF1 0x218
#define UART_XOFF2 0x21c
#define UART_BASE 0xa0080000
enum uart_baudrate {
UART_38400,
UART_57600,
UART_115200,
UART_230400,
UART_460800,
UART_614400,
UART_921600,
};
#define UART_BAUD_RATE UART_115200
#if 0
/* 26MHz clock input (used when no PLL initialized directly after poweron) */
static const uint16_t divider[] = {
[UART_38400] = 42,
[UART_57600] = 28,
[UART_115200] = 14,
[UART_230400] = 7,
[UART_460800] = 14, /* would need UART_REG(HIGHSPEED) = 1 or 2 */
[UART_921600] = 7, /* would need UART_REG(HIGHSPEED) = 2 */
};
#else
/* 52MHz clock input (after PLL init) */
static const uint16_t divider[] = {
[UART_38400] = 85,
[UART_57600] = 56,
[UART_115200] = 28,
[UART_230400] = 14,
[UART_460800] = 7,
[UART_921600] = 7, /* would need UART_REG(HIGHSPEED) = 1 */
};
#endif
static uint8_t uart_getreg(int regnum)
{
volatile uint32_t *reg = (uint32_t *)(UART_BASE + (regnum & 0xff));
return *reg;
}
static void uart_setreg(int regnum, uint8_t val)
{
uint8_t old_lcr;
if (regnum & UART_IS_DLL)
uart_setreg(UART_LCR, uart_getreg(UART_LCR) | 0x80);
else if (regnum & UART_IS_LCR) {
old_lcr = uart_getreg(UART_LCR);
uart_setreg(UART_LCR, 0xbf);
}
volatile uint32_t *reg = (uint32_t *)(UART_BASE + (regnum & 0xff));
*reg = val;
if (regnum & UART_IS_DLL)
uart_setreg(UART_LCR, uart_getreg(UART_LCR) & ~0x80);
else if (regnum & UART_IS_LCR)
uart_setreg(UART_LCR, old_lcr);
}
int serial_putc(uint8_t c)
{
/* Wait for UART to be empty */ /* Wait for UART to be empty */
while (! (*uart_ldr & 0x20)); while (! (uart_getreg(UART_LSR) & 0x20));
*uart_sbr = c;
uart_setreg(UART_RBR, c);
return 0; return 0;
} }
int uart_puts(char *s) { uint8_t serial_getc(void)
while(*s) { {
if (*s == '\n') while (! (uart_getreg(UART_LSR) & 0x01));
uart_putc('\r'); return uart_getreg(UART_RBR);
uart_putc(*s++); }
int serial_puts(void *s)
{
char *str = s;
while(*str) {
if (*str == '\n')
serial_putc('\r');
serial_putc(*str++);
} }
return 0; return 0;
} }
void serial_init(void)
{
int tmp;
// Setup 8-N-1,(UART_WLS_8 | UART_NONE_PARITY | UART_1_STOP) = 0x03
uart_setreg(UART_LCR, 0x03);
// Set BaudRate
// config by UART_BAUD_RATE(9:115200)
uart_setreg(UART_DLL, divider[UART_BAUD_RATE]&0xff);
uart_setreg(UART_DLH, divider[UART_BAUD_RATE]>>8);
uart_setreg(UART_LCR, 0x03);
// Enable Fifo, and Rx Trigger level = 16bytes, flush Tx, Rx fifo
// (UART_FCR_FIFOEN | UART_FCR_4Byte_Level | UART_FCR_RFR | UART_FCR_TFR) = 0x47
uart_setreg(UART_FCR, 0x47);
// DTR , RTS is on, data will be coming,Output2 is high
uart_setreg(UART_MCR, 0x03);
/* Set up normal interrupts */
uart_setreg(UART_IER, 0x0d);
/* Pause a while */
for (tmp=0; tmp<0xff; tmp++);
}

2
spin.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/sh
sudo radare2 -c 's 0x3460; wf .//build/firmware.bin; !echo 0 > /sys/class/gpio/gpio17/value; !sleep 0.05; !echo 1 > /sys/class/gpio/gpio17/value' fv://

20
start.S
View file

@ -27,23 +27,3 @@ do_fiq:
.text .text
.global other
other:
add r1, r2, r1
bx lr
.global __start
__start:
add r3, r2, r3
bx lr
.global _start
_start:
add r4, r3, r4
bx lr
.global other2
other2:
add r5, r4, r5
bx lr

63
utils.c Normal file
View file

@ -0,0 +1,63 @@
#include <stdint.h>
#include "serial.h"
static inline int _isprint(char c)
{
return c > 32 && c < 127;
}
#define HEX_CHARS "0123456789abcdef"
void serial_puth(uint32_t pair, int digits)
{
if (digits >= 8)
serial_putc(HEX_CHARS[(pair >> 28) & 0xf]);
if (digits >= 7)
serial_putc(HEX_CHARS[(pair >> 24) & 0xf]);
if (digits >= 6)
serial_putc(HEX_CHARS[(pair >> 20) & 0xf]);
if (digits >= 5)
serial_putc(HEX_CHARS[(pair >> 16) & 0xf]);
if (digits >= 4)
serial_putc(HEX_CHARS[(pair >> 12) & 0xf]);
if (digits >= 3)
serial_putc(HEX_CHARS[(pair >> 8) & 0xf]);
if (digits >= 2)
serial_putc(HEX_CHARS[(pair >> 4) & 0xf]);
if (digits >= 1)
serial_putc(HEX_CHARS[(pair >> 0) & 0xf]);
}
int serial_print_hex_offset(uint8_t *block, int count, int offset)
{
int byte;
count += offset;
block -= offset;
for ( ; offset < count; offset += 16) {
serial_puth(offset, 8);
for (byte = 0; byte < 16; byte++) {
if (byte == 8)
serial_putc(' ');
serial_putc(' ');
if (offset + byte < count)
serial_puth(block[offset + byte] & 0xff, 2);
else
serial_puts(" ");
}
serial_puts(" |");
for (byte = 0; byte < 16 && byte + offset < count; byte++)
serial_putc(_isprint(block[offset + byte]) ?
block[offset + byte] :
'.');
serial_puts("|\n");
}
return 0;
}
int serial_print_hex(void *block, int count)
{
return serial_print_hex_offset(block, count, 0);
}