You aint taking this down

This commit is contained in:
Slluxx 2023-05-09 01:53:15 +02:00
parent 0bcd59d0cb
commit a2679d92c9
398 changed files with 116325 additions and 35 deletions

37
bdk/utils/aarch64_util.h Normal file
View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARM64_H_
#define _ARM64_H_
#include <utils/types.h>
#define LSL0 0
#define LSL16 16
#define LSL32 32
#define _PAGEOFF(x) ((x) & 0xFFFFF000)
#define _ADRP(r, o) (0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F))
#define _BL(a, o) (0x94000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF))
#define _B(a, o) (0x14000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF))
#define _MOVKX(r, i, s) (0xF2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F))
#define _MOVZX(r, i, s) (0xD2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F))
#define _MOVZW(r, i, s) (0x52800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F))
#define _NOP() 0xD503201F
#endif

114
bdk/utils/btn.c Normal file
View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "btn.h"
#include <soc/i2c.h>
#include <soc/gpio.h>
#include <soc/t210.h>
#include <utils/util.h>
#include <power/max77620.h>
u8 btn_read()
{
u8 res = 0;
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_7))
res |= BTN_VOL_DOWN;
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
res |= BTN_VOL_UP;
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & MAX77620_ONOFFSTAT_EN0)
res |= BTN_POWER;
return res;
}
u8 btn_read_vol()
{
u8 res = 0;
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_7))
res |= BTN_VOL_DOWN;
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
res |= BTN_VOL_UP;
return res;
}
u8 btn_wait()
{
u8 res = 0, btn = btn_read();
bool pwr = false;
//Power button down, raise a filter.
if (btn & BTN_POWER)
{
pwr = true;
btn &= ~BTN_POWER;
}
do
{
res = btn_read();
//Power button up, remove filter.
if (!(res & BTN_POWER) && pwr)
pwr = false;
else if (pwr) //Power button still down.
res &= ~BTN_POWER;
} while (btn == res);
return res;
}
u8 btn_wait_timeout(u32 time_ms, u8 mask)
{
u32 timeout = get_tmr_ms() + time_ms;
u8 res = btn_read() & mask;
while (get_tmr_ms() < timeout)
{
if (res == mask)
break;
else
res = btn_read() & mask;
};
return res;
}
u8 btn_wait_timeout_single(u32 time_ms, u8 mask)
{
u8 single_button = mask & BTN_SINGLE;
mask &= ~BTN_SINGLE;
u32 timeout = get_tmr_ms() + time_ms;
u8 res = btn_read();
while (get_tmr_ms() < timeout)
{
if ((res & mask) == mask)
{
if (single_button && (res & ~mask)) // Undesired button detected.
res = btn_read();
else
return (res & mask);
}
else
res = btn_read();
};
// Timed out.
if (!single_button || !time_ms)
return (res & mask);
else
return 0; // Return no button press if single button requested.
}

34
bdk/utils/btn.h Normal file
View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _BTN_H_
#define _BTN_H_
#include <utils/types.h>
#define BTN_POWER BIT(0)
#define BTN_VOL_DOWN BIT(1)
#define BTN_VOL_UP BIT(2)
#define BTN_SINGLE BIT(7)
u8 btn_read();
u8 btn_read_vol();
u8 btn_wait();
u8 btn_wait_timeout(u32 time_ms, u8 mask);
u8 btn_wait_timeout_single(u32 time_ms, u8 mask);
#endif

100
bdk/utils/dirlist.c Normal file
View file

@ -0,0 +1,100 @@
/*
* Copyright (c) 2018 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stdlib.h>
#include <libs/fatfs/ff.h>
#include <mem/heap.h>
#include <utils/types.h>
#define MAX_ENTRIES 64
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
{
int res = 0;
u32 i = 0, j = 0, k = 0;
DIR dir;
FILINFO fno;
char *dir_entries = (char *)calloc(MAX_ENTRIES, 256);
char *temp = (char *)calloc(1, 256);
if (!pattern && !f_opendir(&dir, directory))
{
for (;;)
{
res = f_readdir(&dir, &fno);
if (res || !fno.fname[0])
break;
bool curr_parse = parse_dirs ? (fno.fattrib & AM_DIR) : !(fno.fattrib & AM_DIR);
if (curr_parse)
{
if ((fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID)))
{
strcpy(dir_entries + (k * 256), fno.fname);
k++;
if (k > (MAX_ENTRIES - 1))
break;
}
}
}
f_closedir(&dir);
}
else if (pattern && !f_findfirst(&dir, &fno, directory, pattern) && fno.fname[0])
{
do
{
if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID)))
{
strcpy(dir_entries + (k * 256), fno.fname);
k++;
if (k > (MAX_ENTRIES - 1))
break;
}
res = f_findnext(&dir, &fno);
} while (fno.fname[0] && !res);
f_closedir(&dir);
}
if (!k)
{
free(temp);
free(dir_entries);
return NULL;
}
// Reorder ini files by ASCII ordering.
for (i = 0; i < k - 1 ; i++)
{
for (j = i + 1; j < k; j++)
{
if (strcmp(&dir_entries[i * 256], &dir_entries[j * 256]) > 0)
{
strcpy(temp, &dir_entries[i * 256]);
strcpy(&dir_entries[i * 256], &dir_entries[j * 256]);
strcpy(&dir_entries[j * 256], temp);
}
}
}
free(temp);
return dir_entries;
}

19
bdk/utils/dirlist.h Normal file
View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2018 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <utils/types.h>
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs);

192
bdk/utils/ini.c Normal file
View file

@ -0,0 +1,192 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "ini.h"
#include <libs/fatfs/ff.h>
#include <mem/heap.h>
#include <utils/dirlist.h>
static char *_strdup(char *str)
{
if (!str)
return NULL;
// Remove starting space.
if (str[0] == ' ' && strlen(str))
str++;
char *res = (char *)malloc(strlen(str) + 1);
strcpy(res, str);
// Remove trailing space.
if (strlen(res) && res[strlen(res) - 1] == ' ')
res[strlen(res) - 1] = 0;
return res;
}
u32 _find_section_name(char *lbuf, u32 lblen, char schar)
{
u32 i;
// Depends on 'FF_USE_STRFUNC 2' that removes \r.
for (i = 0; i < lblen && lbuf[i] != schar && lbuf[i] != '\n'; i++)
;
lbuf[i] = 0;
return i;
}
ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type)
{
if (csec)
list_append(dst, &csec->link);
csec = (ini_sec_t *)calloc(sizeof(ini_sec_t), 1);
csec->name = _strdup(name);
csec->type = type;
return csec;
}
int ini_parse(link_t *dst, char *ini_path, bool is_dir)
{
FIL fp;
u32 lblen;
u32 pathlen = strlen(ini_path);
u32 k = 0;
ini_sec_t *csec = NULL;
char *lbuf = NULL;
char *filelist = NULL;
char *filename = (char *)malloc(256);
strcpy(filename, ini_path);
// Get all ini filenames.
if (is_dir)
{
filelist = dirlist(filename, "*.ini", false, false);
if (!filelist)
{
free(filename);
return 0;
}
strcpy(filename + pathlen, "/");
pathlen++;
}
do
{
// Copy ini filename in path string.
if (is_dir)
{
if (filelist[k * 256])
{
strcpy(filename + pathlen, &filelist[k * 256]);
k++;
}
else
break;
}
// Open ini.
if (f_open(&fp, filename, FA_READ) != FR_OK)
{
free(filelist);
free(filename);
return 0;
}
lbuf = malloc(512);
do
{
// Fetch one line.
lbuf[0] = 0;
f_gets(lbuf, 512, &fp);
lblen = strlen(lbuf);
// Remove trailing newline. Depends on 'FF_USE_STRFUNC 2' that removes \r.
if (lblen && lbuf[lblen - 1] == '\n')
lbuf[lblen - 1] = 0;
if (lblen > 2 && lbuf[0] == '[') // Create new section.
{
_find_section_name(lbuf, lblen, ']');
csec = _ini_create_section(dst, csec, &lbuf[1], INI_CHOICE);
list_init(&csec->kvs);
}
else if (lblen > 1 && lbuf[0] == '{') // Create new caption. Support empty caption '{}'.
{
_find_section_name(lbuf, lblen, '}');
csec = _ini_create_section(dst, csec, &lbuf[1], INI_CAPTION);
csec->color = 0xFF0AB9E6;
}
else if (lblen > 2 && lbuf[0] == '#') // Create comment.
{
csec = _ini_create_section(dst, csec, &lbuf[1], INI_COMMENT);
}
else if (lblen < 2) // Create empty line.
{
csec = _ini_create_section(dst, csec, NULL, INI_NEWLINE);
}
else if (csec && csec->type == INI_CHOICE) // Extract key/value.
{
u32 i = _find_section_name(lbuf, lblen, '=');
ini_kv_t *kv = (ini_kv_t *)calloc(sizeof(ini_kv_t), 1);
kv->key = _strdup(&lbuf[0]);
kv->val = _strdup(&lbuf[i + 1]);
list_append(&csec->kvs, &kv->link);
}
} while (!f_eof(&fp));
f_close(&fp);
if (csec)
{
list_append(dst, &csec->link);
if (is_dir)
csec = NULL;
}
} while (is_dir);
free(lbuf);
free(filename);
free(filelist);
return 1;
}
char *ini_check_payload_section(ini_sec_t *cfg)
{
if (cfg == NULL)
return NULL;
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg->kvs, link)
{
if (!strcmp("payload", kv->key))
return kv->val;
}
return NULL;
}

50
bdk/utils/ini.h Normal file
View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _INI_H_
#define _INI_H_
#include <utils/types.h>
#include <utils/list.h>
#define INI_CHOICE 3
#define INI_CAPTION 5
#define INI_CHGLINE 6
#define INI_NEWLINE 0xFE
#define INI_COMMENT 0xFF
typedef struct _ini_kv_t
{
char *key;
char *val;
link_t link;
} ini_kv_t;
typedef struct _ini_sec_t
{
char *name;
link_t kvs;
link_t link;
u32 type;
u32 color;
} ini_sec_t;
int ini_parse(link_t *dst, char *ini_path, bool is_dir);
char *ini_check_payload_section(ini_sec_t *cfg);
#endif

97
bdk/utils/list.h Normal file
View file

@ -0,0 +1,97 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _LIST_H_
#define _LIST_H_
#include <utils/types.h>
/*! Initialize list. */
#define LIST_INIT(name) link_t name = {&name, &name}
/*! Initialize static list. */
#define LIST_INIT_STATIC(name) static link_t name = {&name, &name}
/*! Iterate over all list links. */
#define LIST_FOREACH(iter, list) \
for(link_t *iter = (list)->next; iter != (list); iter = iter->next)
/*! Safely iterate over all list links. */
#define LIST_FOREACH_SAFE(iter, list) \
for(link_t *iter = (list)->next, *safe = iter->next; iter != (list); iter = safe, safe = iter->next)
/*! Iterate over all list members and make sure that the list has at least one entry. */
#define LIST_FOREACH_ENTRY(etype, iter, list, mn) \
if ((list)->next != (list)) \
for(etype *iter = CONTAINER_OF((list)->next, etype, mn); &iter->mn != (list); iter = CONTAINER_OF(iter->mn.next, etype, mn))
typedef struct _link_t
{
struct _link_t *prev;
struct _link_t *next;
} link_t;
static inline void link_init(link_t *l)
{
l->prev = NULL;
l->next = NULL;
}
static inline int link_used(link_t *l)
{
if(l->next == NULL)
return 1;
return 0;
}
static inline void list_init(link_t *lh)
{
lh->prev = lh;
lh->next = lh;
}
static inline void list_prepend(link_t *lh, link_t *l)
{
l->next = lh->next;
l->prev = lh;
lh->next->prev = l;
lh->next = l;
}
static inline void list_append(link_t *lh, link_t *l)
{
l->prev = lh->prev;
l->next = lh;
lh->prev->next = l;
lh->prev = l;
}
static inline void list_remove(link_t *l)
{
l->next->prev = l->prev;
l->prev->next = l->next;
link_init(l);
}
static inline int list_empty(link_t *lh)
{
if(lh->next == lh)
return 1;
return 0;
}
#endif

123
bdk/utils/sprintf.c Normal file
View file

@ -0,0 +1,123 @@
/*
* Copyright (c) 2019-2020 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sprintf.h"
#include <stdarg.h>
static void _putc(char *buffer, const char c) {
*buffer = c;
}
static u32 _puts(char *buffer, const char *s) {
u32 count = 0;
for (; *s; s++, count++)
_putc(buffer + count, *s);
return count;
}
static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) {
char buf[0x121];
static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
char *p;
int c = fcnt;
if (base > 36)
return 0;
p = buf + 0x120;
*p = 0;
do {
c--;
*--p = digits[v % base];
v /= base;
} while (v);
if (fill != 0) {
while (c > 0) {
*--p = fill;
c--;
}
}
return _puts(buffer, p);
}
u32 s_printf(char *buffer, const char *fmt, ...) {
va_list ap;
int fill, fcnt;
u32 count = 0;
va_start(ap, fmt);
while(*fmt) {
if (*fmt == '%') {
fmt++;
fill = 0;
fcnt = 0;
if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ') {
fcnt = *fmt;
fmt++;
if (*fmt >= '0' && *fmt <= '9') {
fill = fcnt;
fcnt = *fmt - '0';
fmt++;
} else {
fill = ' ';
fcnt -= '0';
}
}
switch (*fmt) {
case 'c':
_putc(buffer + count, va_arg(ap, u32));
count++;
break;
case 's':
count += _puts(buffer + count, va_arg(ap, char *));
break;
case 'd':
count += _putn(buffer + count, va_arg(ap, u32), 10, fill, fcnt);
break;
case 'p':
case 'P':
case 'x':
case 'X':
count += _putn(buffer + count, va_arg(ap, u32), 16, fill, fcnt);
break;
case '%':
_putc(buffer + count, '%');
count++;
break;
case '\0':
goto out;
default:
_putc(buffer + count, '%');
count++;
_putc(buffer + count, *fmt);
count++;
break;
}
} else {
_putc(buffer + count, *fmt);
count++;
}
fmt++;
}
out:
buffer[count] = 0;
va_end(ap);
return count;
}

24
bdk/utils/sprintf.h Normal file
View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2019-2020 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SPRINTF_H_
#define _SPRINTF_H_
#include "types.h"
u32 s_printf(char *buffer, const char *fmt, ...);
#endif

197
bdk/utils/types.h Normal file
View file

@ -0,0 +1,197 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TYPES_H_
#define _TYPES_H_
#include <assert.h>
/* Types */
typedef signed char s8;
typedef short s16;
typedef short SHORT;
typedef int s32;
typedef int INT;
typedef int bool;
typedef long LONG;
typedef long long int s64;
typedef unsigned char u8;
typedef unsigned char BYTE;
typedef unsigned short u16;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
typedef unsigned int u32;
typedef unsigned int UINT;
typedef unsigned long DWORD;
typedef unsigned long long QWORD;
typedef unsigned long long int u64;
typedef volatile unsigned char vu8;
typedef volatile unsigned short vu16;
typedef volatile unsigned int vu32;
#ifdef __aarch64__
typedef u64 uptr;
#else /* __arm__ or __thumb__ */
typedef u32 uptr;
#endif
/* Colors */
#define COLOR_RED 0xFFE70000
#define COLOR_ORANGE 0xFFFF8C00
#define COLOR_YELLOW 0xFFFFFF40
#define COLOR_GREEN 0xFF40FF00
#define COLOR_BLUE 0xFF00DDFF
#define COLOR_VIOLET 0xFF8040FF
static const u32 colors[6] = {COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_BLUE, COLOR_VIOLET};
/* Important */
#define false 0
#define true 1
#define NULL ((void *)0)
/* Misc */
#define DISABLE 0
#define ENABLE 1
/* Sizes */
#define SZ_1K 0x400
#define SZ_2K 0x800
#define SZ_4K 0x1000
#define SZ_8K 0x2000
#define SZ_16K 0x4000
#define SZ_32K 0x8000
#define SZ_64K 0x10000
#define SZ_128K 0x20000
#define SZ_256K 0x40000
#define SZ_512K 0x80000
#define SZ_1M 0x100000
#define SZ_2M 0x200000
#define SZ_4M 0x400000
#define SZ_8M 0x800000
#define SZ_16M 0x1000000
#define SZ_32M 0x2000000
#define SZ_64M 0x4000000
#define SZ_128M 0x8000000
#define SZ_256M 0x10000000
#define SZ_512M 0x20000000
#define SZ_1G 0x40000000
#define SZ_2G 0x80000000
#define SZ_PAGE SZ_4K
/* Macros */
#define ALWAYS_INLINE inline __attribute__((always_inline))
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ALIGN_DOWN(x, a) ((x) & ~((a) - 1))
#define BIT(n) (1U << (n))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define DIV_ROUND_UP(a, b) ((a + b - 1) / b)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
#define LOG2(n) (32 - __builtin_clz(n) - 1)
#define CLZ(n) __builtin_clz(n)
#define CLO(n) __builtin_clz(~n)
#define OFFSET_OF(t, m) ((uptr)&((t *)NULL)->m)
#define CONTAINER_OF(mp, t, mn) ((t *)((uptr)mp - OFFSET_OF(t, mn)))
#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00))
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
/* Bootloader/Nyx */
#define BOOT_CFG_AUTOBOOT_EN BIT(0)
#define BOOT_CFG_FROM_LAUNCH BIT(1)
#define BOOT_CFG_FROM_ID BIT(2)
#define BOOT_CFG_TO_EMUMMC BIT(3)
#define EXTRA_CFG_KEYS BIT(0)
#define EXTRA_CFG_PAYLOAD BIT(1)
#define EXTRA_CFG_MODULE BIT(2)
#define EXTRA_CFG_NYX_UMS BIT(5)
#define EXTRA_CFG_NYX_RELOAD BIT(6)
typedef enum _nyx_ums_type
{
NYX_UMS_SD_CARD = 0,
NYX_UMS_EMMC_BOOT0,
NYX_UMS_EMMC_BOOT1,
NYX_UMS_EMMC_GPP,
NYX_UMS_EMUMMC_BOOT0,
NYX_UMS_EMUMMC_BOOT1,
NYX_UMS_EMUMMC_GPP
} nyx_ums_type;
typedef struct __attribute__((__packed__)) _boot_cfg_t
{
u8 boot_cfg;
u8 autoboot;
u8 autoboot_list;
u8 extra_cfg;
union
{
struct
{
char id[8]; // 7 char ASCII null teminated.
char emummc_path[0x78]; // emuMMC/XXX, ASCII null teminated.
};
u8 ums; // nyx_ums_type.
u8 xt_str[0x80];
};
} boot_cfg_t;
static_assert(sizeof(boot_cfg_t) == 0x84, "Boot cfg storage size is wrong!");
typedef struct __attribute__((__packed__)) _ipl_ver_meta_t
{
u32 magic;
u32 version;
u16 rsvd0;
u16 rsvd1;
} ipl_ver_meta_t;
typedef struct __attribute__((__packed__)) _reloc_meta_t
{
u32 start;
u32 stack;
u32 end;
u32 ep;
} reloc_meta_t;
typedef enum
{
VALIDITY_UNCHECKED = 0,
VALIDITY_INVALID,
VALIDITY_VALID
} validity_t;
typedef enum
{
OPEN_MODE_READ = 1,
OPEN_MODE_WRITE = 2,
OPEN_MODE_ALLOW_APPEND = 4,
OPEN_MODE_READ_WRITE = OPEN_MODE_READ | OPEN_MODE_WRITE,
OPEN_MODE_ALL = OPEN_MODE_READ | OPEN_MODE_WRITE | OPEN_MODE_ALLOW_APPEND
} open_mode_t;
#endif

232
bdk/utils/util.c Normal file
View file

@ -0,0 +1,232 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
# Copyright (c) 2022 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <utils/util.h>
#include <mem/heap.h>
#include <power/max77620.h>
#include <rtc/max77620-rtc.h>
#include <soc/bpmp.h>
#include <soc/hw_init.h>
#include <soc/i2c.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <storage/nx_sd.h>
#define USE_RTC_TIMER
extern volatile nyx_storage_t *nyx_str;
u8 bit_count(u32 val)
{
u8 cnt = 0;
for (u32 i = 0; i < 32; i++)
{
if ((val >> i) & 1)
cnt++;
}
return cnt;
}
u32 bit_count_mask(u8 bits)
{
u32 val = 0;
for (u32 i = 0; i < bits; i++)
val |= 1 << i;
return val;
}
u32 get_tmr_s()
{
return RTC(APBDEV_RTC_SECONDS);
}
u32 get_tmr_ms()
{
// The registers must be read with the following order:
// RTC_MILLI_SECONDS (0x10) -> RTC_SHADOW_SECONDS (0xC)
return (RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000));
}
u32 get_tmr_us()
{
return TMR(TIMERUS_CNTR_1US);
}
void msleep(u32 ms)
{
#ifdef USE_RTC_TIMER
u32 start = RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000);
// Casting to u32 is important!
while (((u32)(RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000)) - start) <= ms)
;
#else
bpmp_msleep(ms);
#endif
}
void usleep(u32 us)
{
#ifdef USE_RTC_TIMER
u32 start = TMR(TIMERUS_CNTR_1US);
// Check if timer is at upper limits and use BPMP sleep so it doesn't wake up immediately.
if ((start + us) < start)
bpmp_usleep(us);
else
while ((u32)(TMR(TIMERUS_CNTR_1US) - start) <= us) // Casting to u32 is important!
;
#else
bpmp_usleep(us);
#endif
}
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops)
{
for(u32 i = 0; i < num_ops; i++)
base[ops[i].off] = ops[i].val;
}
u16 crc16_calc(const u8 *buf, u32 len)
{
const u8 *p, *q;
u16 crc = 0x55aa;
static u16 table[16] = {
0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400
};
q = buf + len;
for (p = buf; p < q; p++)
{
u8 oct = *p;
crc = (crc >> 4) ^ table[crc & 0xf] ^ table[(oct >> 0) & 0xf];
crc = (crc >> 4) ^ table[crc & 0xf] ^ table[(oct >> 4) & 0xf];
}
return crc;
}
u32 crc32_calc(u32 crc, const u8 *buf, u32 len)
{
const u8 *p, *q;
static u32 *table = NULL;
// Calculate CRC table.
if (!table)
{
table = calloc(256, sizeof(u32));
for (u32 i = 0; i < 256; i++)
{
u32 rem = i;
for (u32 j = 0; j < 8; j++)
{
if (rem & 1)
{
rem >>= 1;
rem ^= 0xedb88320;
}
else
rem >>= 1;
}
table[i] = rem;
}
}
crc = ~crc;
q = buf + len;
for (p = buf; p < q; p++)
{
u8 oct = *p;
crc = (crc >> 8) ^ table[(crc & 0xff) ^ oct];
}
return ~crc;
}
void panic(u32 val)
{
// Set panic code.
PMC(APBDEV_PMC_SCRATCH200) = val;
//PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_DISABLE;
TMR(TIMER_WDT4_UNLOCK_PATTERN) = TIMER_MAGIC_PTRN;
TMR(TIMER_TMR9_TMR_PTV) = TIMER_EN | TIMER_PER_EN;
TMR(TIMER_WDT4_CONFIG) = TIMER_SRC(9) | TIMER_PER(1) | TIMER_PMCRESET_EN;
TMR(TIMER_WDT4_COMMAND) = TIMER_START_CNT;
while (true)
usleep(1);
}
void power_set_state(power_state_t state)
{
u8 reg;
// Unmount and power down sd card.
sd_end();
// De-initialize and power down various hardware.
hw_reinit_workaround(false, 0);
// Stop the alarm, in case we injected and powered off too fast.
max77620_rtc_stop_alarm();
// Set power state.
switch (state)
{
case REBOOT_RCM:
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; // Enable RCM path.
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; // PMC reset.
break;
case REBOOT_BYPASS_FUSES:
panic(0x21); // Bypass fuse programming in package1.
break;
case POWER_OFF:
// Initiate power down sequence and do not generate a reset (regulators retain state).
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
break;
case POWER_OFF_RESET:
case POWER_OFF_REBOOT:
default:
// Enable/Disable soft reset wake event.
reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
if (state == POWER_OFF_RESET) // Do not wake up after power off.
reg &= ~(MAX77620_ONOFFCNFG2_SFT_RST_WK | MAX77620_ONOFFCNFG2_WK_ALARM1 | MAX77620_ONOFFCNFG2_WK_ALARM2);
else // POWER_OFF_REBOOT. Wake up after power off.
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
// Initiate power down sequence and generate a reset (regulators' state resets).
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST);
break;
}
while (true)
bpmp_halt();
}
void power_set_state_ex(void *param)
{
power_state_t *state = (power_state_t *)param;
power_set_state(*state);
}

99
bdk/utils/util.h Normal file
View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _UTIL_H_
#define _UTIL_H_
#include <utils/types.h>
#include <mem/minerva.h>
#define NYX_NEW_INFO 0x3058594E
typedef enum
{
REBOOT_RCM, // PMC reset. Enter RCM mode.
REBOOT_BYPASS_FUSES, // PMC reset via watchdog. Enter Normal mode. Bypass fuse programming in package1.
POWER_OFF, // Power off PMIC. Do not reset regulators.
POWER_OFF_RESET, // Power off PMIC. Reset regulators.
POWER_OFF_REBOOT, // Power off PMIC. Reset regulators. Power on.
} power_state_t;
typedef enum
{
NYX_CFG_UMS = BIT(6),
NYX_CFG_EXTRA = 0xFF << 24
} nyx_cfg_t;
typedef enum
{
ERR_LIBSYS_LP0 = BIT(0),
ERR_SYSOLD_NYX = BIT(1),
ERR_LIBSYS_MTC = BIT(2),
ERR_SD_BOOT_EN = BIT(3),
ERR_PANIC_CODE = BIT(4),
ERR_L4T_KERNEL = BIT(24),
ERR_EXCEPTION = BIT(31),
} hekate_errors_t;
typedef struct _cfg_op_t
{
u32 off;
u32 val;
} cfg_op_t;
typedef struct _nyx_info_t
{
u32 magic;
u32 sd_init;
u32 sd_errors[3];
u8 rsvd[0x1000];
u32 disp_id;
u32 errors;
} nyx_info_t;
typedef struct _nyx_storage_t
{
u32 version;
u32 cfg;
u8 irama[0x8000];
u8 hekate[0x30000];
u8 rsvd[SZ_8M - sizeof(nyx_info_t)];
nyx_info_t info;
mtc_config_t mtc_cfg;
emc_table_t mtc_table[10];
} nyx_storage_t;
u8 bit_count(u32 val);
u32 bit_count_mask(u8 bits);
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u16 crc16_calc(const u8 *buf, u32 len);
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
u32 get_tmr_us();
u32 get_tmr_ms();
u32 get_tmr_s();
void usleep(u32 us);
void msleep(u32 ms);
void panic(u32 val);
void power_set_state(power_state_t state);
void power_set_state_ex(void *param);
#endif