fernly: More blocks discovered
This commit is contained in:
parent
685824f56e
commit
9470228966
11 changed files with 1385 additions and 41 deletions
4
Makefile
4
Makefile
|
@ -10,7 +10,9 @@ LIBS =
|
|||
SRC_C = \
|
||||
main.c \
|
||||
vectors.c \
|
||||
serial.c
|
||||
serial.c \
|
||||
utils.c \
|
||||
bionic.c
|
||||
|
||||
SRC_S = \
|
||||
start.S
|
||||
|
|
125
README.md
125
README.md
|
@ -17,3 +17,128 @@ To install, use radare2:
|
|||
[0x00000000]> s 0x3460
|
||||
[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
663
bionic.c
Normal 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
11
include/bionic.h
Normal 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__ */
|
|
@ -1,9 +1,15 @@
|
|||
#ifndef __UART_H__
|
||||
#define __UART_H__
|
||||
#ifndef __SERIAL_H__
|
||||
#define __SERIAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int uart_putc(uint8_t c);
|
||||
int uart_puts(char *s);
|
||||
int serial_putc(uint8_t c);
|
||||
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
5
include/utils.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#ifndef __UTILS_H__
|
||||
#define __UTILS_H__
|
||||
#include <stdint.h>
|
||||
|
||||
#endif /* __UTILS_H__ */
|
374
main.c
374
main.c
|
@ -1,10 +1,374 @@
|
|||
#include <string.h>
|
||||
#include "serial.h"
|
||||
#include "utils.h"
|
||||
#include "bionic.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
while(1) {
|
||||
int i;
|
||||
uart_puts("Hello, world!\n");
|
||||
for (i = 0; i < 0xf000; i++);
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
143
serial.c
143
serial.c
|
@ -1,20 +1,143 @@
|
|||
#include <stdint.h>
|
||||
#include "serial.h"
|
||||
|
||||
int uart_putc(uint8_t c) {
|
||||
uint32_t *uart_ldr = (uint32_t *)0xa0080014;
|
||||
uint32_t *uart_sbr = (uint32_t *)0xa0080000;
|
||||
|
||||
#define UART_IS_DLL 0x100
|
||||
#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 */
|
||||
while (! (*uart_ldr & 0x20));
|
||||
*uart_sbr = c;
|
||||
while (! (uart_getreg(UART_LSR) & 0x20));
|
||||
|
||||
uart_setreg(UART_RBR, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uart_puts(char *s) {
|
||||
while(*s) {
|
||||
if (*s == '\n')
|
||||
uart_putc('\r');
|
||||
uart_putc(*s++);
|
||||
uint8_t serial_getc(void)
|
||||
{
|
||||
while (! (uart_getreg(UART_LSR) & 0x01));
|
||||
return uart_getreg(UART_RBR);
|
||||
}
|
||||
|
||||
int serial_puts(void *s)
|
||||
{
|
||||
char *str = s;
|
||||
while(*str) {
|
||||
if (*str == '\n')
|
||||
serial_putc('\r');
|
||||
serial_putc(*str++);
|
||||
}
|
||||
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
2
spin.sh
Executable 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
20
start.S
|
@ -27,23 +27,3 @@ do_fiq:
|
|||
|
||||
.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
63
utils.c
Normal 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);
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue