Compare commits

..

55 Commits
v3.2 ... v4.2

Author SHA1 Message Date
Kostas Missos
fac8db4238 Bump version to v4.2 2018-09-24 23:51:36 +03:00
Kostas Missos
04ac8ebd43 Allow verification cancel. Backup still remains. 2018-09-24 23:51:04 +03:00
Kostas Missos
1392e6eaf4 Add use of wildcard "*" for loading kips from a folder 2018-09-24 23:47:35 +03:00
Kostas Missos
381d5c9236 Allow toggling of auto power off from HOS waking 2018-09-24 23:45:06 +03:00
Kostas Missos
2f43b20124 Bugfixes / formating 2018-09-24 23:22:19 +03:00
Kostas Missos
c99ea77daf Bump version to v4.1 2018-09-19 17:58:26 +03:00
Kostas Missos
4ad7aedbaf -.-
Nintendo, I Am Disappoint
2018-09-19 17:57:02 +03:00
Kostas Missos
267bcd352f [PATCH] Port FS patches to 6.0.0
Co-Authored-By: Rajko Stojadinovic <admin@rajko.info>
2018-09-19 00:57:19 +03:00
Kostas Missos
db88eb31f2 Add svc/dbg &Atmosphère fs.mitm patches for 6.0.0 2018-09-19 00:55:26 +03:00
Kostas Missos
efc3fc34de Add cancel backup if VOL DOWN + UP are held
- Long press of both buttons cancels the backup process now
- Fixed an issue with partial backup when the resume was happening on the last part
2018-09-19 00:50:23 +03:00
Kostas Missos
89fb29e35e Add support for payloads with broken hw inits 2018-09-19 00:46:32 +03:00
Kostas Missos
b54cbbfc3c Fix version check for the update chainloader 2018-09-19 00:36:40 +03:00
Kostas Missos
fc0f75495e Add auto full power off if woke up from HOS.
Useful for modchips/dongles.
It shows a brief breathing style of hekate logo before powering off completely.
2018-09-19 00:34:05 +03:00
Kostas Missos
4e9b3d8157 Add proper BCT copy for dev units
Co-Authored-By: Rajko Stojadinovic <admin@rajko.info>
2018-09-19 00:28:13 +03:00
Kostas Missos
7aeac2c379 Add 4/5.X and 6.X hw config changes
Thanks to @balika011 for notice on 2.x vs 5.x changes.

(Some 2.x vs 5.x changes were added with the `fdd94ff` commit)
2018-09-19 00:11:18 +03:00
Kostas Missos
b9e348fc17 Add warnings on missing bootloader libraries 2018-09-19 00:04:58 +03:00
Kostas Missos
67a470921a Add PWM backlight support + options
- No eye blasting backlight
- Option to choose the prefered brightness
- Smooths transitions
2018-09-19 00:01:42 +03:00
Kostas Missos
780736591e Improvements to ini/payload handling
- Allow no hekate_ipl.ini and create it at 1st hekate boot
- Show Payloads/More configs options when no boot entry in main .ini
- Fix black screen on empty ini/payload folders
- Fix some stack corruption with freeing ini lists (wip)
2018-09-18 23:47:37 +03:00
Kostas Missos
fdd94ffd2b General bugfixes + hardcoded name replacement 2018-09-18 23:38:54 +03:00
Kostas Missos
59e711c91d Merge remote-tracking branch 'origin/dev' 2018-09-18 03:18:26 +03:00
Pika
4e43bd9a39 Add 6.0.0 support (#95)
Add partial 6.0.0 support
2018-09-18 03:08:05 +03:00
Kostas Missos
5aecd0d778 Merge pull request #107 from balika011/dev
Add ipatch and bootrom dumping
2018-09-10 15:50:38 +03:00
balika011
532dd6ddee Add ipatch and bootrom dumping 2018-09-10 01:12:28 +02:00
Kostas Missos
58b289bee2 Fix build pf sample module by adding missing files 2018-08-25 22:59:54 +03:00
Kostas Missos
6da09b3b93 Bump version to v4.0 2018-08-23 05:06:10 +03:00
Kostas Missos
7803bbcd83 Add payload launching. Supports all CFW bins, Linux, Tools. 2018-08-23 05:05:31 +03:00
Kostas Missos
382f727be3 Fix all the bugs
- Mem leaks
- Stack corruption
- Div by 0
- Double frees
2018-08-23 04:37:02 +03:00
Kostas Missos
6a554eec6c Update Readme + Fix Auto Update 2018-08-23 04:27:49 +03:00
Kostas Missos
0540128709 Faster backups
- Add file pre-allocations to greatly reduce overhead of FatFS.
This was missing before, because it takes 1.5KB payload size.

Speed bumps (no verify) are between 7 to 30% for exFAT and ~50% for FAT32, depending on the workload.
2018-08-22 03:42:25 +03:00
Kostas Missos
da5a1a9641 Fix a critical bug with exFAT FatFs + a list bug
Nintendo you hear? Fix your driver already.
(for us never caused any problem, because we always sync fs dir changes to medium.)
2018-08-22 03:38:25 +03:00
Kostas Missos
c5a6ad823e Add payload/libtools launching prerequisites 2018-08-21 04:45:19 +03:00
Kostas Missos
463383abca AutoRCM disabler support for all AutoRCM versions 2018-08-21 04:43:00 +03:00
Kostas Missos
13a07663ee Add autolaunch updated bootloader (mostly for modchips) 2018-08-21 04:41:16 +03:00
Kostas Missos
5328f89ffe Add support for split inis in 'bootloader/ini'
- A new option was added to Launch.
- These can be configured for autoboot
2018-08-21 04:37:40 +03:00
Kostas Missos
7e876388b4 Bugfixes
- Fixed partial dumping filename/bar position
- Add return for menu function handler
- More files to bootloader folder
2018-08-21 04:26:14 +03:00
Kostas Missos
bf816c5107 Move everything to 'bootloader' folder to reduce clutter
+ Make everything all lowercase
2018-08-21 04:21:09 +03:00
Kostas Missos
1d623eacf9 Our 1st module. LP0 configuration. 2018-08-21 04:14:31 +03:00
Kostas Missos
3d6216a6f3 Deploy ianos. Our elf/module loader. 2018-08-21 04:12:03 +03:00
Kostas Missos
5fd9daa364 Add display_end fix for all fw + easter egg
The easter egg is sth that was forgotten in booting via hekate's hwinit.
2018-08-14 02:30:44 +03:00
Kostas Missos
6b8887b5d8 Move display_end before secmon + add boolean supp.
Currently bpmp loses access to the relevant registers when secmon or exosphere is launched.

This change provides support for all firmwares and properly sanitizes the display.
2018-08-13 12:12:53 +03:00
Kostas Missos
e5abdd938e Refactor ALL the things + enable LTO 2018-08-13 11:58:24 +03:00
Kostas Missos
2666b440ef Merge pull request #66 from m4xw/feature/elf_loader
Implement basic elfloader/module support
2018-08-08 00:25:40 +03:00
M4xw
8b0915cb01 Implement elfloader/module support 2018-08-07 22:41:05 +02:00
Kostas Missos
71c4e2c155 Merge pull request #63 from misson20000/misson20000-patch-1
Update README.md to document `atmosphere` option in hekate.ini
2018-08-06 10:15:41 +03:00
misson20000
6baeb8b4ff Update README.md to document atmosphere option in hekate.ini 2018-08-05 22:08:17 -07:00
Kostas Missos
355ebb6acf Whitespaces, fixes 2018-08-05 14:40:32 +03:00
Kostas Missos
c9379d97a3 Merge pull request #62 from rajkosto/pull_improvenogc
Better nogc patch, no longer causes 10s hang on bootup and wakeup
2018-08-05 13:50:08 +03:00
Rajko Stojadinovic
c2da65e498 Better nogc patch, no longer causes 10s hang on bootup and wakeup 2018-08-05 06:27:18 +02:00
Kostas Missos
e9d1256df8 Merge pull request #51 from rajkosto/kip1patching
Add KIP1 patching support (with 2 FS patches included)
2018-07-29 23:09:25 +03:00
Rajko Stojadinovic
977ef6f150 Add KIP1 patching support (with 2 FS patches included) 2018-07-29 22:03:12 +02:00
Kostas Missos
d33f60e924 Add unique id to backup folder
+ Choose to boot into HOS if no SD card or .ini

*The unique id for the backup folder is eMMC's serial number.
2018-07-22 15:24:09 +03:00
Kostas Missos
39653f7678 Bugfixes + Unfattening + Remove white on boot 2018-07-22 15:18:30 +03:00
Kostas Missos
bc67798f43 More unfattening (like always) 2018-07-10 16:59:03 +03:00
tesnos
9401897f93 Allow dumping TSEC keys to sd card (#44)
* Allow dumping tsec keys to sd card
2018-07-10 10:19:06 +03:00
Kostas Missos
1988e3f19d Bump version to v3.2
Forgot to commit that ^^
2018-07-09 23:22:11 +03:00
148 changed files with 12187 additions and 6377 deletions

4
.gitignore vendored
View File

@@ -1,4 +1,4 @@
.vs
.vscode
build_ipl/*
/ipl.bin
build/*
output/*

View File

@@ -4,10 +4,15 @@ endif
include $(DEVKITARM)/base_rules
TARGET := ipl
BUILD := build_ipl
SOURCEDIR := ipl
OBJS = $(addprefix $(BUILD)/, \
TARGET := hekate
BLVERSION_MAJOR := 4
BLVERSION_MINOR := 2
BUILD := build
OUTPUT := output
SOURCEDIR = bootloader
VPATH = $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
OBJS = $(addprefix $(BUILD)/$(TARGET)/, \
start.o \
main.o \
config.o \
@@ -20,7 +25,6 @@ OBJS = $(addprefix $(BUILD)/, \
hos.o \
i2c.o \
kfuse.o \
lz.o \
bq24193.o \
max7762x.o \
max17050.o \
@@ -29,7 +33,6 @@ OBJS = $(addprefix $(BUILD)/, \
sdmmc.o \
sdmmc_driver.o \
sdram.o \
sdram_lp0.o \
tui.o \
util.o \
di.o \
@@ -40,36 +43,52 @@ OBJS = $(addprefix $(BUILD)/, \
se.o \
tsec.o \
uart.o \
dirlist.o \
ini.o \
ianos.o \
)
OBJS += $(addprefix $(BUILD)/$(TARGET)/, \
lz.o blz.o \
diskio.o ff.o ffunicode.o ffsystem.o \
elfload.o elfreloc_arm.o \
)
OBJS += $(addprefix $(BUILD)/, diskio.o ff.o ffunicode.o ffsystem.o)
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CUSTOMDEFINES := -DMENU_LOGO_ENABLE
CUSTOMDEFINES := -DBLVERSIONMJ=$(BLVERSION_MAJOR) -DBLVERSIONMN=$(BLVERSION_MINOR)
CUSTOMDEFINES += -DMENU_LOGO_ENABLE #-DDEBUG
CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections
.PHONY: all clean
MODULEDIRS := $(wildcard modules/*)
.PHONY: all clean $(MODULEDIRS)
all: $(TARGET).bin
@echo -n "Payload size is "
@wc -c < $(TARGET).bin
@wc -c < $(OUTPUT)/$(TARGET).bin
@echo "Max size is 126296 Bytes."
clean:
@rm -rf $(OBJS)
@rm -rf $(BUILD)
@rm -rf $(TARGET).bin
@rm -rf $(OUTPUT)
$(TARGET).bin: $(BUILD)/$(TARGET).elf
$(OBJCOPY) -S -O binary $< $@
$(MODULEDIRS):
$(MAKE) -C $@ $(MAKECMDGOALS)
$(BUILD)/$(TARGET).elf: $(OBJS)
$(CC) $(LDFLAGS) -T ipl/link.ld $^ -o $@
$(TARGET).bin: $(BUILD)/$(TARGET)/$(TARGET).elf $(MODULEDIRS)
$(OBJCOPY) -S -O binary $< $(OUTPUT)/$@
@printf ICTC$(BLVERSION_MAJOR)$(BLVERSION_MINOR) >> $(OUTPUT)/$@
$(BUILD)/%.o: $(SOURCEDIR)/%.c
$(BUILD)/$(TARGET)/$(TARGET).elf: $(OBJS)
$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
$(BUILD)/$(TARGET)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
$(BUILD)/%.o: $(SOURCEDIR)/%.S
$(BUILD)/$(TARGET)/%.o: %.S
@mkdir -p "$(BUILD)"
@mkdir -p "$(BUILD)/$(TARGET)"
@mkdir -p "$(OUTPUT)"
$(CC) $(CFLAGS) -c $< -o $@

View File

@@ -6,9 +6,24 @@
Custom Nintendo Switch bootloader, firmware patcher, and more.
## IPL configuration
## Bootloader folders and files
The ipl can be configured via 'hekate_ipl.ini' (if it is present on the SD card). Each ini section represents a boot entry, except for the special section 'config' that controls the global configuration.
| Folder/File | Description |
| -------------------- | --------------------------------------------------------------------- |
| bootloader | Main folder. |
| \|__ bootlogo.bmp | It is used when custom is on and no logopath found. Can be skipped. |
| \|__ hekate_ipl.ini | Main bootloader configuration and boot entries. |
| \|__ update.bin | If newer, it is loaded at boot. For modchips. Can be skipped. |
| bootloader/ini/ | For individual inis. 'More configs...' menu. Autoboot is supported. |
| bootloader/sys/ | For system modules. |
| \|__ libsys_lp0.bso | LP0 (sleep mode) module. Important! |
| bootloader/payloads/ | For payloads. 'Payloads...' menu. Autoboot only supported by including them into an ini. All CFW bootloaders, tools, Linux payloads are supported. |
| bootloader/libtools/ | Future reserved |
## Bootloader configuration
The bootloader can be configured via 'bootloader/hekate_ipl.ini' (if it is present on the SD card). Each ini section represents a boot entry, except for the special section 'config' that controls the global configuration.
There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Caption, "**#**": Comment, "*newline*": .ini cosmetic newline.
@@ -19,9 +34,11 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
| Config option | Description |
| ------------------ | ---------------------------------------------------------- |
| autoboot=0 | 0: Disable, #: Boot entry number to auto boot. |
| bootwait=3 | 0: Disable (Having VOL- pressed since injection goes to menu. It also disables bootlogo.), #: Time to wait for **VOL-** to enter menu. |
| bootwait=3 | 0: Disable (It also disables bootlogo. Having **VOL-** pressed since injection goes to menu.), #: Time to wait for **VOL-** to enter menu. |
| customlogo=0 | 0: Use default hekate bootlogo, 1: Use bootlogo.bmp. |
| verification=2 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and not 100% reliable), 2: Full (sha256 based, slow and 100% reliable). |
| autohosoff=1 | If woke up from HOS via an rtc alarm, power off completely.|
| backlight=100 | Screen backlight level. 0-255. |
### Possible boot entry key/value combinations:
@@ -33,12 +50,18 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
| secmon={SD path} | Replaces the security monitor binary |
| kernel={SD path} | Replaces the kernel binary |
| kip1={SD path} | Replaces/Adds kernel initial process. Multiple can be set. |
| fullsvcperm=1 | Disables SVC verification |
| kip1={SD folder}/* | Loads every .kip/.kip1 inside a folder. Compatible with single kip1 keys. |
| kip1patch=patchname| Enables a kip1 patch. Specify with multiple lines and/or as CSV. Implemented patches right now are nosigchk,nogc |
| fullsvcperm=1 | Disables SVC verification (full services permission) |
| debugmode=1 | Enables Debug mode |
| atmosphere=1 | Enables Atmosphère patching |
| payload={SD path} | Payload launching. Tools, Linux, CFW bootloaders, etc. |
You can find a template [Here](./res/hekate_ipl_template.ini)
If the main .ini is not found, it is created on the first hekate boot.
```
hekate (C) 2018 naehrwert, st4rk
@@ -51,6 +74,7 @@ Open source and free packages used:
- FatFs R0.13a, Copyright (C) 2017, ChaN
- bcl-1.2.0, Copyright (C) 2003-2006, Marcus Geelnard
- Atmosphère (SE sha256, prc id kernel patches), Copyright (C) 2018, Atmosphère-NX
- elfload, Copyright (C) 2014 Owen Shepherd, Copyright (C) 2018 M4xw
___
.-' `'.

699
bootloader/config/config.c Normal file
View File

@@ -0,0 +1,699 @@
/*
* 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 "../utils/btn.h"
#include "config.h"
#include "../libs/fatfs/ff.h"
#include "ini.h"
#include "../utils/list.h"
#include "../gfx/tui.h"
#include "../utils/util.h"
#include "../gfx/gfx.h"
extern gfx_ctxt_t gfx_ctxt;
extern gfx_con_t gfx_con;
//TODO: Create more macros (info, header, debug, etc) with different colors and utilize them for consistency.
#define EPRINTF(text) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFF0000, 0xFFCCCCCC)
#define EPRINTFARGS(text, args...) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC)
extern hekate_config h_cfg;
extern int sd_mount();
extern int sd_unmount();
void set_default_configuration()
{
h_cfg.autoboot = 0;
h_cfg.autoboot_list = 0;
h_cfg.bootwait = 3;
h_cfg.customlogo = 0;
h_cfg.verification = 2;
h_cfg.se_keygen_done = 0;
h_cfg.sbar_time_keeping = 0;
h_cfg.backlight = 100;
h_cfg.autohosoff = 1;
h_cfg.errors = 0;
}
int create_config_entry()
{
if (!sd_mount())
return 1;
char lbuf[16];
FIL fp;
bool mainIniFound = false;
LIST_INIT(ini_sections);
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
mainIniFound = true;
else
{
u8 res = f_open(&fp, "bootloader/hekate_ipl.ini", FA_READ);
if (res == FR_NO_FILE || res == FR_NO_PATH)
{
f_mkdir("bootloader");
f_mkdir("bootloader/ini");
f_mkdir("bootloader/payloads");
f_mkdir("bootloader/sys");
}
else
{
if (!res)
f_close(&fp);
return 1;
}
}
if (f_open(&fp, "bootloader/hekate_ipl.ini", FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
return 1;
// Add config entry.
f_puts("[config]\nautoboot=", &fp);
itoa(h_cfg.autoboot, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\nautoboot_list=", &fp);
itoa(h_cfg.autoboot_list, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\nbootwait=", &fp);
itoa(h_cfg.bootwait, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\ncustomlogo=", &fp);
itoa(h_cfg.customlogo, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\nverification=", &fp);
itoa(h_cfg.verification, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\nbacklight=", &fp);
itoa(h_cfg.backlight, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\nautohosoff=", &fp);
itoa(h_cfg.autohosoff, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\n", &fp);
if (mainIniFound)
{
// Re-construct existing entries.
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{
if (!strcmp(ini_sec->name, "config"))
continue;
switch (ini_sec->type)
{
case INI_CHOICE: // Re-construct Boot entry [ ].
f_puts("[", &fp);
f_puts(ini_sec->name, &fp);
f_puts("]\n", &fp);
// Re-construct boot entry's config.
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
f_puts(kv->key, &fp);
f_puts("=", &fp);
f_puts(kv->val, &fp);
f_puts("\n", &fp);
}
break;
case INI_CAPTION: // Re-construct caption entry { }.
f_puts("{", &fp);
f_puts(ini_sec->name, &fp);
f_puts("}\n", &fp);
break;
case INI_NEWLINE: // Re-construct cosmetic newline \n.
f_puts("\n", &fp);
break;
case INI_COMMENT: // Re-construct comment entry #.
f_puts("#", &fp);
f_puts(ini_sec->name, &fp);
f_puts("\n", &fp);
break;
}
}
}
f_close(&fp);
sd_unmount();
if (mainIniFound)
ini_free(&ini_sections);
return 0;
}
void _config_autoboot_list()
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
u32 *temp_autoboot = NULL;
LIST_INIT(ini_sections);
u8 max_entries = 30;
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
u32 *boot_values = (u32 *)malloc(sizeof(u32) * max_entries);
char *boot_text = (char *)malloc(512 * max_entries);
for (u32 j = 0; j < max_entries; j++)
boot_values[j] = j;
if (sd_mount())
{
if (ini_parse(&ini_sections, "bootloader/ini", true))
{
// Build configuration menu.
ments[0].type = MENT_BACK;
ments[0].caption = "Back";
ments[1].type = MENT_CHGLINE;
u32 i = 2;
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{
// Skip other ini entries for autoboot.
if (ini_sec->type == INI_CHOICE)
{
if (!strcmp(ini_sec->name, "config"))
continue;
if (strlen(ini_sec->name) > 510)
ments[i].caption = ini_sec->name;
else
{
if (h_cfg.autoboot != (i - 1) || !h_cfg.autoboot_list)
boot_text[(i - 1) * 512] = ' ';
else
boot_text[(i - 1) * 512] = '*';
memcpy(boot_text + (i - 1) * 512 + 1, ini_sec->name, strlen(ini_sec->name) + 1);
boot_text[strlen(ini_sec->name) + (i - 1) * 512 + 1] = 0;
ments[i].caption = &boot_text[(i - 1) * 512];
}
ments[i].type = ini_sec->type;
ments[i].data = &boot_values[i - 1];
i++;
if ((i - 1) > max_entries)
break;
}
}
memset(&ments[i], 0, sizeof(ment_t));
menu_t menu = {ments, "Select a list entry to auto boot", 0, 0};
temp_autoboot = (u32 *)tui_do_menu(&gfx_con, &menu);
if (temp_autoboot != NULL)
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
h_cfg.autoboot = *(u32 *)temp_autoboot;
h_cfg.autoboot_list = 1;
// Save choice to ini file.
if (!create_config_entry())
gfx_puts(&gfx_con, "\nConfiguration was saved!\n");
else
EPRINTF("\nConfiguration saving failed!");
gfx_puts(&gfx_con, "\nPress any key...");
}
else
goto out2;
}
else
{
EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists in SD Card!.");
goto out;
}
}
out:;
btn_wait();
out2:;
free(ments);
free(boot_values);
free(boot_text);
ini_free(&ini_sections);
sd_unmount();
if (temp_autoboot == NULL)
return;
}
void config_autoboot()
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
u32 *temp_autoboot = NULL;
LIST_INIT(ini_sections);
u8 max_entries = 30;
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 5));
u32 *boot_values = (u32 *)malloc(sizeof(u32) * max_entries);
char *boot_text = (char *)malloc(512 * max_entries);
for (u32 j = 0; j < max_entries; j++)
boot_values[j] = j;
if (sd_mount())
{
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
{
// Build configuration menu.
ments[0].type = MENT_BACK;
ments[0].caption = "Back";
ments[1].type = MENT_CHGLINE;
ments[2].type = MENT_DATA;
if (!h_cfg.autoboot)
ments[2].caption = "*Disable";
else
ments[2].caption = " Disable";
ments[2].data = &boot_values[0];
ments[3].type = MENT_HANDLER;
if (h_cfg.autoboot_list)
ments[3].caption = "*More configs...";
else
ments[3].caption = " More configs...";
ments[3].handler = _config_autoboot_list;
ments[3].data = NULL;
ments[4].type = MENT_CHGLINE;
u32 i = 5;
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{
// Skip other ini entries for autoboot.
if (ini_sec->type == INI_CHOICE)
{
if (!strcmp(ini_sec->name, "config"))
continue;
if (strlen(ini_sec->name) > 510)
ments[i].caption = ini_sec->name;
else
{
if (h_cfg.autoboot != (i - 4) || h_cfg.autoboot_list)
boot_text[(i - 4) * 512] = ' ';
else
boot_text[(i - 4) * 512] = '*';
memcpy(boot_text + (i - 4) * 512 + 1, ini_sec->name, strlen(ini_sec->name) + 1);
boot_text[strlen(ini_sec->name) + (i - 4) * 512 + 1] = 0;
ments[i].caption = &boot_text[(i - 4) * 512];
}
ments[i].type = ini_sec->type;
ments[i].data = &boot_values[i - 4];
i++;
if ((i - 4) > max_entries)
break;
}
}
if (i < 6 && !h_cfg.autoboot_list)
{
ments[i].type = MENT_CAPTION;
ments[i].caption = "No main configurations found...";
ments[i].color = 0xFFFFDD00;
i++;
}
memset(&ments[i], 0, sizeof(ment_t));
menu_t menu = {ments, "Disable or select entry to auto boot", 0, 0};
temp_autoboot = (u32 *)tui_do_menu(&gfx_con, &menu);
if (temp_autoboot != NULL)
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
h_cfg.autoboot = *(u32 *)temp_autoboot;
h_cfg.autoboot_list = 0;
// Save choice to ini file.
if (!create_config_entry())
gfx_puts(&gfx_con, "\nConfiguration was saved!\n");
else
EPRINTF("\nConfiguration saving failed!");
gfx_puts(&gfx_con, "\nPress any key...");
}
else
goto out2;
}
else
{
EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists in SD Card!.");
goto out;
}
}
out:;
btn_wait();
out2:;
free(ments);
free(boot_values);
free(boot_text);
ini_free(&ini_sections);
sd_unmount();
if (temp_autoboot == NULL)
return;
}
void config_bootdelay()
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
u32 delay_entries = 6;
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (delay_entries + 3));
u32 *delay_values = (u32 *)malloc(sizeof(u32) * delay_entries);
char *delay_text = (char *)malloc(32 * delay_entries);
for (u32 j = 0; j < delay_entries; j++)
delay_values[j] = j;
ments[0].type = MENT_BACK;
ments[0].caption = "Back";
ments[1].type = MENT_CHGLINE;
ments[2].type = MENT_DATA;
if (h_cfg.bootwait)
ments[2].caption = " 0 seconds (Bootlogo disabled)";
else
ments[2].caption = "*0 seconds (Bootlogo disabled)";
ments[2].data = &delay_values[0];
u32 i = 0;
for (i = 1; i < delay_entries; i++)
{
if (h_cfg.bootwait != i)
delay_text[i * 32] = ' ';
else
delay_text[i * 32] = '*';
delay_text[i * 32 + 1] = i + '0';
memcpy(delay_text + i * 32 + 2, " seconds", 9);
ments[i + 2].type = MENT_DATA;
ments[i + 2].caption = delay_text + i * 32;
ments[i + 2].data = &delay_values[i];
}
memset(&ments[i + 2], 0, sizeof(ment_t));
menu_t menu = {ments, "Time delay for entering bootloader menu", 0, 0};
u32 *temp_bootwait = (u32 *)tui_do_menu(&gfx_con, &menu);
if (temp_bootwait != NULL)
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
h_cfg.bootwait = *(u32 *)temp_bootwait;
// Save choice to ini file.
if (!create_config_entry())
gfx_puts(&gfx_con, "\nConfiguration was saved!\n");
else
EPRINTF("\nConfiguration saving failed!");
gfx_puts(&gfx_con, "\nPress any key...");
}
free(ments);
free(delay_values);
free(delay_text);
if (temp_bootwait == NULL)
return;
btn_wait();
}
void config_customlogo()
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 5);
u32 *cb_values = (u32 *)malloc(sizeof(u32) * 2);
for (u32 j = 0; j < 2; j++)
{
cb_values[j] = j;
ments[j + 2].type = MENT_DATA;
ments[j + 2].data = &cb_values[j];
}
ments[0].type = MENT_BACK;
ments[0].caption = "Back";
ments[1].type = MENT_CHGLINE;
if (h_cfg.customlogo)
{
ments[2].caption = " Disable";
ments[3].caption = "*Enable";
}
else
{
ments[2].caption = "*Disable";
ments[3].caption = " Enable";
}
memset(&ments[4], 0, sizeof(ment_t));
menu_t menu = {ments, "Custom bootlogo", 0, 0};
u32 *temp_customlogo = (u32 *)tui_do_menu(&gfx_con, &menu);
if (temp_customlogo != NULL)
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
h_cfg.customlogo = *(u32 *)temp_customlogo;
// Save choice to ini file.
if (!create_config_entry())
gfx_puts(&gfx_con, "\nConfiguration was saved!\n");
else
EPRINTF("\nConfiguration saving failed!");
gfx_puts(&gfx_con, "\nPress any key...");
}
free(ments);
free(cb_values);
if (temp_customlogo == NULL)
return;
btn_wait();
}
void config_verification()
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6);
u32 *vr_values = (u32 *)malloc(sizeof(u32) * 3);
char *vr_text = (char *)malloc(64 * 3);
for (u32 j = 0; j < 3; j++)
{
vr_values[j] = j;
ments[j + 2].type = MENT_DATA;
ments[j + 2].data = &vr_values[j];
}
ments[0].type = MENT_BACK;
ments[0].caption = "Back";
ments[1].type = MENT_CHGLINE;
memcpy(vr_text, " Disable (Fastest)", 19);
memcpy(vr_text + 64, " Sparse (Fast - Not reliable)", 32);
memcpy(vr_text + 128, " Full (Slow - 100% reliable)", 32);
for (u32 i = 0; i < 3; i++)
{
if (h_cfg.verification != i)
{
vr_text[64 * i] = ' ';
ments[2 + i].caption = vr_text + (i * 64);
}
else
{
vr_text[64 * i] = '*';
ments[2 + i].caption = vr_text + (i * 64);
}
}
memset(&ments[5], 0, sizeof(ment_t));
menu_t menu = {ments, "Backup & Restore verification", 0, 0};
u32 *temp_verification = (u32 *)tui_do_menu(&gfx_con, &menu);
if (temp_verification != NULL)
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
h_cfg.verification = *(u32 *)temp_verification;
// Save choice to ini file.
if (!create_config_entry())
gfx_puts(&gfx_con, "\nConfiguration was saved!\n");
else
EPRINTF("\nConfiguration saving failed!");
gfx_puts(&gfx_con, "\nPress any key...");
}
free(ments);
free(vr_values);
free(vr_text);
if (temp_verification == NULL)
return;
btn_wait();
}
void config_backlight()
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
u32 bri_entries = 11;
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (bri_entries + 3));
u32 *bri_values = (u32 *)malloc(sizeof(u32) * bri_entries);
char *bri_text = (char *)malloc(8 * bri_entries);
for (u32 j = 1; j < bri_entries; j++)
bri_values[j] = j * 10;
ments[0].type = MENT_BACK;
ments[0].caption = "Back";
ments[1].type = MENT_CHGLINE;
u32 i = 0;
for (i = 1; i < bri_entries; i++)
{
if ((h_cfg.backlight / 20) != i)
bri_text[i * 32] = ' ';
else
bri_text[i * 32] = '*';
if (i < 10)
{
bri_text[i * 32 + 1] = i + '0';
memcpy(bri_text + i * 32 + 2, "0%", 3);
}
else
memcpy(bri_text + i * 32 + 1, "100%", 5);
ments[i + 1].type = MENT_DATA;
ments[i + 1].caption = bri_text + i * 32;
ments[i + 1].data = &bri_values[i];
}
memset(&ments[i + 1], 0, sizeof(ment_t));
menu_t menu = {ments, "Backlight brightness", 0, 0};
u32 *temp_backlight = (u32 *)tui_do_menu(&gfx_con, &menu);
if (temp_backlight != NULL)
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
h_cfg.backlight = (*(u32 *)temp_backlight) * 2;
//Save choice to ini file.
if (!create_config_entry())
gfx_puts(&gfx_con, "\nConfiguration was saved!\n");
else
EPRINTF("\nConfiguration saving failed!");
gfx_puts(&gfx_con, "\nPress any key...");
}
free(ments);
free(bri_values);
free(bri_text);
if (temp_backlight == NULL)
return;
btn_wait();
}
void config_auto_hos_poweroff()
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 5);
u32 *hp_values = (u32 *)malloc(sizeof(u32) * 2);
for (u32 j = 0; j < 2; j++)
{
hp_values[j] = j;
ments[j + 2].type = MENT_DATA;
ments[j + 2].data = &hp_values[j];
}
ments[0].type = MENT_BACK;
ments[0].caption = "Back";
ments[1].type = MENT_CHGLINE;
if (h_cfg.autohosoff)
{
ments[2].caption = " Disable";
ments[3].caption = "*Enable";
}
else
{
ments[2].caption = "*Disable";
ments[3].caption = " Enable";
}
memset(&ments[4], 0, sizeof(ment_t));
menu_t menu = {ments, "Power off if woke up from HOS", 0, 0};
u32 *temp_autohosoff = (u32 *)tui_do_menu(&gfx_con, &menu);
if (temp_autohosoff != NULL)
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
h_cfg.autohosoff = *(u32 *)temp_autohosoff;
// Save choice to ini file.
if (!create_config_entry())
gfx_puts(&gfx_con, "\nConfiguration was saved!\n");
else
EPRINTF("\nConfiguration saving failed!");
gfx_puts(&gfx_con, "\nPress any key...");
}
free(ments);
free(hp_values);
if (temp_autohosoff == NULL)
return;
btn_wait();
}

View File

@@ -0,0 +1,52 @@
/*
* 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 _CONFIG_H_
#define _CONFIG_H_
#include "../utils/types.h"
typedef struct _hekate_config
{
// Non-volatile config.
u32 autoboot;
u32 autoboot_list;
u32 bootwait;
u32 customlogo;
u32 verification;
u32 backlight;
u32 autohosoff;
u32 errors;
// Global temporary config.
int se_keygen_done;
u32 sbar_time_keeping;
} hekate_config;
typedef enum
{
ERR_LIBSYS_LP0 = (1 << 0),
} hsysmodule_t;
void set_default_configuration();
int create_config_entry();
void config_autoboot();
void config_bootdelay();
void config_customlogo();
void config_verification();
void config_backlight();
void config_auto_hos_poweroff();
#endif /* _CONFIG_H_ */

260
bootloader/config/ini.c Normal file
View File

@@ -0,0 +1,260 @@
/*
* 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 <string.h>
#include "ini.h"
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#include "../utils/dirlist.h"
static char *_strdup(char *str)
{
char *res = (char *)malloc(strlen(str) + 1);
strcpy(res, str);
return res;
}
int ini_parse(link_t *dst, char *ini_path, bool is_dir)
{
u32 lblen;
u32 pathlen = strlen(ini_path);
u32 k = 0;
char lbuf[512];
char *filelist = NULL;
FIL fp;
ini_sec_t *csec = NULL;
char *filename = (char *)malloc(256);
memcpy(filename, ini_path, pathlen + 1);
if (is_dir)
{
filelist = dirlist(filename, "*.ini");
if (!filelist)
{
free(filename);
return 0;
}
memcpy(filename + pathlen, "/", 2);
pathlen++;
}
do
{
if (is_dir)
{
if (filelist[k * 256])
{
memcpy(filename + pathlen, &filelist[k * 256], strlen(&filelist[k * 256]) + 1);
k++;
}
else
break;
}
if (f_open(&fp, filename, FA_READ) != FR_OK)
{
free(filelist);
free(filename);
return 0;
}
do
{
// Fetch one line.
lbuf[0] = 0;
f_gets(lbuf, 512, &fp);
lblen = strlen(lbuf);
// Remove trailing newline.
if (lbuf[lblen - 1] == '\n')
lbuf[lblen - 1] = 0;
if (lblen > 2 && lbuf[0] == '[') // Create new section.
{
if (csec)
{
list_append(dst, &csec->link);
csec = NULL;
}
u32 i;
for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != ']'; i++)
;
lbuf[i] = 0;
csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
csec->name = _strdup(&lbuf[1]);
csec->type = INI_CHOICE;
list_init(&csec->kvs);
}
else if (lblen > 2 && lbuf[0] == '{') //Create new caption.
{
if (csec)
{
list_append(dst, &csec->link);
csec = NULL;
}
u32 i;
for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != '}'; i++)
;
lbuf[i] = 0;
csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
csec->name = _strdup(&lbuf[1]);
csec->type = INI_CAPTION;
csec->color = 0xFF0AB9E6;
}
else if (lblen > 2 && lbuf[0] == '#') //Create empty lines and comments.
{
if (csec)
{
list_append(dst, &csec->link);
csec = NULL;
}
u32 i;
for (i = 0; i < lblen && lbuf[i] != '\n'; i++)
;
lbuf[i] = 0;
csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
csec->name = _strdup(&lbuf[1]);
csec->type = INI_COMMENT;
}
else if (lblen < 2)
{
if (csec)
{
list_append(dst, &csec->link);
csec = NULL;
}
csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
csec->name = NULL;
csec->type = INI_NEWLINE;
}
else if (csec && csec->type == INI_CHOICE) //Extract key/value.
{
u32 i;
for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != '='; i++)
;
lbuf[i] = 0;
ini_kv_t *kv = (ini_kv_t *)malloc(sizeof(ini_kv_t));
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);
} while (is_dir);
free(filename);
free(filelist);
return 1;
}
void ini_free(link_t *dst)
{
if (!dst->prev || !dst->next)
return;
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, dst, link)
{
if (ini_sec->type == INI_CHOICE)
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
free(kv->key);
free(kv->val);
//free(kv);
}
}
free(ini_sec->name);
//free(ini_sec);
}
list_init(dst);
}
ini_sec_t *ini_clone_section(ini_sec_t *cfg)
{
if (cfg == NULL)
return NULL;
ini_sec_t *csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
list_init(&csec->kvs);
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg->kvs, link)
{
ini_kv_t *kvcfg = (ini_kv_t *)malloc(sizeof(ini_kv_t));
kvcfg->key = _strdup(kv->key);
kvcfg->val = _strdup(kv->val);
list_append(&csec->kvs, &kvcfg->link);
}
return csec;
}
void ini_free_section(ini_sec_t *cfg)
{
if (cfg == NULL)
return;
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg->kvs, link)
{
free(kv->key);
free(kv->val);
free(kv);
}
free(cfg);
cfg = NULL;
}
char *ini_check_payload_section(ini_sec_t *cfg)
{
char *path = NULL;
if (cfg == NULL)
return NULL;
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg->kvs, link)
{
if (!strcmp("payload", kv->key))
{
if (!path)
path = _strdup(kv->val);
}
}
if (path)
return path;
else
return NULL;
}

53
bootloader/config/ini.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* 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);
void ini_free(link_t *dst);
ini_sec_t *ini_clone_section(ini_sec_t *cfg);
void ini_free_section(ini_sec_t *cfg);
char *ini_check_payload_section(ini_sec_t *cfg);
#endif

161
ipl/di.c → bootloader/gfx/di.c Executable file → Normal file
View File

@@ -1,31 +1,31 @@
/*
* 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/>.
*/
* 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 <string.h>
#include "di.h"
#include "t210.h"
#include "util.h"
#include "i2c.h"
#include "pmc.h"
#include "max77620.h"
#include "gpio.h"
#include "pinmux.h"
#include "clock.h"
#include "../soc/t210.h"
#include "../utils/util.h"
#include "../soc/i2c.h"
#include "../soc/pmc.h"
#include "../power/max77620.h"
#include "../soc/gpio.h"
#include "../soc/pinmux.h"
#include "../soc/clock.h"
#include "di.inl"
@@ -41,11 +41,11 @@ static void _display_dsi_wait(u32 timeout, u32 off, u32 mask)
void display_init()
{
//Power on.
i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_LDO0_CFG, 0xD0); //Configure to 1.2V.
i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_GPIO7, 0x09);
// Power on.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO0_CFG, 0xD0); // Configure to 1.2V.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, 0x09);
//Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks.
// Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x1010000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x1010000;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000;
@@ -55,41 +55,41 @@ void display_init()
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = 0x80000;
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 0xA;
//DPD idle.
// DPD idle.
PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000;
PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000;
//Config pins.
// Config pins.
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE;
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO); //Backlight +-5V.
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE); //Backlight +-5V.
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); //Backlight +5V enable.
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO); // Backlight +-5V.
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE); // Backlight +-5V.
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // Backlight +5V enable.
usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); //Backlight -5V enable.
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // Backlight -5V enable.
usleep(10000);
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO); //Backlight PWM, Enable, Reset.
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO); // Backlight PWM, Enable, Reset.
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); //Backlight Enable enable.
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Backlight Enable enable.
//Config display interface and display.
// Config display interface and display.
MIPI_CAL(0x60) = 0;
exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4);
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94);
exec_cfg((u32 *)DSI_BASE, _display_config_3, 60);
exec_cfg((u32 *)DSI_BASE, _display_config_3, 61);
usleep(10000);
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH); //Backlight Reset enable.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH); // Backlight Reset enable.
usleep(60000);
@@ -121,8 +121,8 @@ void display_init()
usleep(20000);
exec_cfg((u32 *)DSI_BASE, _display_config_5, 21);
exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3);
exec_cfg((u32 *)DSI_BASE, _display_config_5, 21);
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4;
exec_cfg((u32 *)DSI_BASE, _display_config_7, 10);
@@ -137,24 +137,58 @@ void display_init()
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113);
}
void display_backlight(u8 enable)
void display_backlight_pwm_init()
{
gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); //Backlight PWM.
clock_enable_pwm();
PWM(PWM_CONTROLLER_PWM_CSR) = (1 << 31); // Enable PWM
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; // PWM clock source.
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode.
}
void display_backlight(bool enable)
{
gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); // Backlight PWM GPIO.
}
void display_backlight_brightness(u32 brightness, u32 step_delay)
{
u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR) >> 16) & 0xFF;
if (brightness == old_value)
return;
if (brightness > 255)
brightness = 255;
if (old_value < brightness)
{
for (u32 i = old_value; i < brightness + 1; i++)
{
PWM(PWM_CONTROLLER_PWM_CSR) = (1 << 31) | (i << 16); // Enable PWM
usleep(step_delay);
}
}
else
{
for (u32 i = old_value; i > brightness; i--)
{
PWM(PWM_CONTROLLER_PWM_CSR) = (1 << 31) | (i << 16); // Enable PWM
usleep(step_delay);
}
}
if (!brightness)
PWM(PWM_CONTROLLER_PWM_CSR) = 0;
}
void display_end()
{
display_backlight(0);
display_backlight_brightness(0, 1000);
//TODO: figure out why this freezes.
/*DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1;
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1;
DSI(_DSIREG(DSI_WR_DATA)) = 0x2805;
u32 end = HOST1X(0x30A4) + 5;
while (HOST1X(0x30A4) < end)
;
DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX;
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
@@ -171,28 +205,28 @@ void display_end()
usleep(50000);
//gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable.
//usleep(10000);
usleep(10000);
//gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable.
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable.
//usleep(10000);
usleep(10000);
//gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable.
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable.
//usleep(10000);
usleep(10000);
//Disable clocks.
// Disable clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x1010000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = 0x1010000;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = 0x18000000;
DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF);
DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;*/
DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); //Backlight PWM.
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1;
@@ -202,7 +236,7 @@ void display_color_screen(u32 color)
{
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8);
//Configure display to show single color.
// Configure display to show single color.
DISPLAY_A(_DIREG(DC_WIN_AD_WIN_OPTIONS)) = 0;
DISPLAY_A(_DIREG(DC_WIN_BD_WIN_OPTIONS)) = 0;
DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0;
@@ -211,20 +245,17 @@ void display_color_screen(u32 color)
usleep(35000);
display_backlight(1);
display_backlight(true);
}
u32 *display_init_framebuffer()
{
//Sanitize framebuffer area.
// Sanitize framebuffer area.
memset((u32 *)0xC0000000, 0, 0x3C0000);
//This configures the framebuffer @ 0xC0000000 with a resolution of 1280x720 (line stride 768).
// This configures the framebuffer @ 0xC0000000 with a resolution of 1280x720 (line stride 768).
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer, 32);
usleep(35000);
//Enable backlight
//display_backlight(1);
return (u32 *)0xC0000000;
}

52
ipl/di.h → bootloader/gfx/di.h Executable file → Normal file
View File

@@ -1,24 +1,24 @@
/*
* 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/>.
*/
* 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 _DI_H_
#define _DI_H_
#include "types.h"
#include "../utils/types.h"
/*! Display registers. */
#define _DIREG(reg) ((reg) * 4)
@@ -80,6 +80,8 @@
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
#define DC_COM_DSC_TOP_CTL 0x33E
#define DC_DISP_DISP_WIN_OPTIONS 0x402
#define HDMI_ENABLE (1 << 30)
#define DSI_ENABLE (1 << 29)
@@ -159,6 +161,8 @@
#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
#define DC_DISP_SD_BL_PARAMETERS 0x4D7
#define DC_DISP_SD_BL_CONTROL 0x4DC
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
#define DC_WIN_CSC_YOF 0x611
@@ -173,10 +177,11 @@
#define DC_WIN_BD_WIN_OPTIONS 0xD80
#define DC_WIN_CD_WIN_OPTIONS 0xF80
//The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER).
// The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER).
#define DC_WIN_WIN_OPTIONS 0x700
#define H_DIRECTION (1 << 0)
#define V_DIRECTION (1 << 2)
#define SCAN_COLUMN (1 << 4)
#define COLOR_EXPAND (1 << 6)
#define CSC_ENABLE (1 << 18)
#define WIN_ENABLE (1 << 30)
@@ -224,9 +229,11 @@
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
#define DC_WIN_LINE_STRIDE 0x70A
#define LINE_STRIDE(x) (x)
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
#define DC_WIN_DV_CONTROL 0x70E
//The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER).
// The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER).
#define DC_WINBUF_START_ADDR 0x800
#define DC_WINBUF_ADDR_H_OFFSET 0x806
#define DC_WINBUF_ADDR_V_OFFSET 0x808
@@ -336,14 +343,21 @@
#define DSI_PAD_CONTROL_4 0x52
#define DSI_INIT_SEQ_DATA_15 0x5F
/*! Display backlight related PWM registers. */
#define PWM_CONTROLLER_PWM_CSR 0x00
void display_init();
void display_backlight_pwm_init();
void display_end();
/*! Show one single color on the display. */
void display_color_screen(u32 color);
/*! Switches screen backlight ON/OFF. */
void display_backlight(u8 enable);
void display_backlight(bool enable);
void display_backlight_brightness(u32 brightness, u32 step_delay);
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
u32 *display_init_framebuffer();

11
ipl/di.inl → bootloader/gfx/di.inl Executable file → Normal file
View File

@@ -128,7 +128,7 @@ static const cfg_op_t _display_config_2[94] = {
};
//DSI Init config.
static const cfg_op_t _display_config_3[60] = {
static const cfg_op_t _display_config_3[61] = {
{DSI_WR_DATA, 0},
{DSI_INT_ENABLE, 0},
{DSI_INT_STATUS, 0},
@@ -137,6 +137,7 @@ static const cfg_op_t _display_config_3[60] = {
{DSI_INIT_SEQ_DATA_1, 0},
{DSI_INIT_SEQ_DATA_2, 0},
{DSI_INIT_SEQ_DATA_3, 0},
{DSI_INIT_SEQ_DATA_15, 0},
{DSI_DCS_CMDS, 0},
{DSI_PKT_SEQ_0_LO, 0},
{DSI_PKT_SEQ_1_LO, 0},
@@ -288,7 +289,7 @@ static const cfg_op_t _display_config_7[10] = {
static const cfg_op_t _display_config_8[6] = {
{0x18, 0},
{2, 0xF3F10000},
{0x16, 1},
{0x16, 0},
{0x18, 0},
{0x18, 0x10010},
{0x17, 0x300}
@@ -474,10 +475,10 @@ static const cfg_op_t _display_config_13[16] = {
{DSI_PAD_CONTROL_1, 0},
{DSI_PHY_TIMING_0, 0x6070601},
{DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30109},
{DSI_PHY_TIMING_2, 0x30118},
{DSI_BTA_TIMING, 0x190A14},
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) },
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
@@ -544,7 +545,7 @@ static const cfg_op_t cfg_display_framebuffer[32] = {
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, //Pre-scaled size: 1280x2880 bytes.
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)},
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, //Window size: 1280 vertical lines x 720 horizontal pixels.
{DC_WIN_LINE_STRIDE, 0x6000C00}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, 0},
{DC_WINBUF_SURFACE_KIND, 0}, //Regular surface.
{DC_WINBUF_START_ADDR, 0xC0000000}, //Framebuffer address.

524
bootloader/gfx/gfx.c Normal file
View File

@@ -0,0 +1,524 @@
/*
* 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 <stdarg.h>
#include <string.h>
#include "gfx.h"
static const u8 _gfx_font[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 032 ( )
0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, // Char 033 (!)
0x00, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, // Char 034 (")
0x00, 0x66, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x66, // Char 035 (#)
0x00, 0x18, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x18, // Char 036 ($)
0x00, 0x46, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x62, // Char 037 (%)
0x00, 0x3C, 0x66, 0x3C, 0x1C, 0xE6, 0x66, 0xFC, // Char 038 (&)
0x00, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, // Char 039 (')
0x00, 0x30, 0x18, 0x0C, 0x0C, 0x18, 0x30, 0x00, // Char 040 (()
0x00, 0x0C, 0x18, 0x30, 0x30, 0x18, 0x0C, 0x00, // Char 041 ())
0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, // Char 042 (*)
0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, // Char 043 (+)
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0C, 0x00, // Char 044 (,)
0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, // Char 045 (-)
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, // Char 046 (.)
0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, // Char 047 (/)
0x00, 0x3C, 0x66, 0x76, 0x6E, 0x66, 0x3C, 0x00, // Char 048 (0)
0x00, 0x18, 0x1C, 0x18, 0x18, 0x18, 0x7E, 0x00, // Char 049 (1)
0x00, 0x3C, 0x62, 0x30, 0x0C, 0x06, 0x7E, 0x00, // Char 050 (2)
0x00, 0x3C, 0x62, 0x38, 0x60, 0x66, 0x3C, 0x00, // Char 051 (3)
0x00, 0x6C, 0x6C, 0x66, 0xFE, 0x60, 0x60, 0x00, // Char 052 (4)
0x00, 0x7E, 0x06, 0x7E, 0x60, 0x66, 0x3C, 0x00, // Char 053 (5)
0x00, 0x3C, 0x06, 0x3E, 0x66, 0x66, 0x3C, 0x00, // Char 054 (6)
0x00, 0x7E, 0x30, 0x30, 0x18, 0x18, 0x18, 0x00, // Char 055 (7)
0x00, 0x3C, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, // Char 056 (8)
0x00, 0x3C, 0x66, 0x7C, 0x60, 0x66, 0x3C, 0x00, // Char 057 (9)
0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, // Char 058 (:)
0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x0C, 0x00, // Char 059 (;)
0x00, 0x70, 0x1C, 0x06, 0x06, 0x1C, 0x70, 0x00, // Char 060 (<)
0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, // Char 061 (=)
0x00, 0x0E, 0x38, 0x60, 0x60, 0x38, 0x0E, 0x00, // Char 062 (>)
0x00, 0x3C, 0x66, 0x30, 0x18, 0x00, 0x18, 0x00, // Char 063 (?)
0x00, 0x3C, 0x66, 0x76, 0x76, 0x06, 0x46, 0x3C, // Char 064 (@)
0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // Char 065 (A)
0x00, 0x3E, 0x66, 0x3E, 0x66, 0x66, 0x3E, 0x00, // Char 066 (B)
0x00, 0x3C, 0x66, 0x06, 0x06, 0x66, 0x3C, 0x00, // Char 067 (C)
0x00, 0x1E, 0x36, 0x66, 0x66, 0x36, 0x1E, 0x00, // Char 068 (D)
0x00, 0x7E, 0x06, 0x1E, 0x06, 0x06, 0x7E, 0x00, // Char 069 (E)
0x00, 0x3E, 0x06, 0x1E, 0x06, 0x06, 0x06, 0x00, // Char 070 (F)
0x00, 0x3C, 0x66, 0x06, 0x76, 0x66, 0x3C, 0x00, // Char 071 (G)
0x00, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // Char 072 (H)
0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, // Char 073 (I)
0x00, 0x78, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, // Char 074 (J)
0x00, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x00, // Char 075 (K)
0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7E, 0x00, // Char 076 (L)
0x00, 0x46, 0x6E, 0x7E, 0x56, 0x46, 0x46, 0x00, // Char 077 (M)
0x00, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x00, // Char 078 (N)
0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // Char 079 (O)
0x00, 0x3E, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x00, // Char 080 (P)
0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x70, 0x00, // Char 081 (Q)
0x00, 0x3E, 0x66, 0x3E, 0x1E, 0x36, 0x66, 0x00, // Char 082 (R)
0x00, 0x3C, 0x66, 0x0C, 0x30, 0x66, 0x3C, 0x00, // Char 083 (S)
0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, // Char 084 (T)
0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // Char 085 (U)
0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // Char 086 (V)
0x00, 0x46, 0x46, 0x56, 0x7E, 0x6E, 0x46, 0x00, // Char 087 (W)
0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, // Char 088 (X)
0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, // Char 089 (Y)
0x00, 0x7E, 0x30, 0x18, 0x0C, 0x06, 0x7E, 0x00, // Char 090 (Z)
0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, // Char 091 ([)
0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00, // Char 092 (\)
0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, // Char 093 (])
0x00, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, // Char 094 (^)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, // Char 095 (_)
0x00, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, // Char 096 (`)
0x00, 0x00, 0x3C, 0x60, 0x7C, 0x66, 0x7C, 0x00, // Char 097 (a)
0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00, // Char 098 (b)
0x00, 0x00, 0x3C, 0x06, 0x06, 0x06, 0x3C, 0x00, // Char 099 (c)
0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, // Char 100 (d)
0x00, 0x00, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00, // Char 101 (e)
0x00, 0x38, 0x0C, 0x3E, 0x0C, 0x0C, 0x0C, 0x00, // Char 102 (f)
0x00, 0x00, 0x7C, 0x66, 0x7C, 0x40, 0x3C, 0x00, // Char 103 (g)
0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x00, // Char 104 (h)
0x00, 0x18, 0x00, 0x1C, 0x18, 0x18, 0x3C, 0x00, // Char 105 (i)
0x00, 0x30, 0x00, 0x30, 0x30, 0x30, 0x1E, 0x00, // Char 106 (j)
0x00, 0x06, 0x06, 0x36, 0x1E, 0x36, 0x66, 0x00, // Char 107 (k)
0x00, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, // Char 108 (l)
0x00, 0x00, 0x66, 0xFE, 0xFE, 0xD6, 0xC6, 0x00, // Char 109 (m)
0x00, 0x00, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x00, // Char 110 (n)
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, // Char 111 (o)
0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x00, // Char 112 (p)
0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x00, // Char 113 (q)
0x00, 0x00, 0x3E, 0x66, 0x06, 0x06, 0x06, 0x00, // Char 114 (r)
0x00, 0x00, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x00, // Char 115 (s)
0x00, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x70, 0x00, // Char 116 (t)
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, // Char 117 (u)
0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // Char 118 (v)
0x00, 0x00, 0xC6, 0xD6, 0xFE, 0x7C, 0x6C, 0x00, // Char 119 (w)
0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, // Char 120 (x)
0x00, 0x00, 0x66, 0x66, 0x7C, 0x60, 0x3C, 0x00, // Char 121 (y)
0x00, 0x00, 0x7E, 0x30, 0x18, 0x0C, 0x7E, 0x00, // Char 122 (z)
0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, 0x18, // Char 123 ({)
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, // Char 124 (|)
0x00, 0x0C, 0x08, 0x08, 0x10, 0x08, 0x08, 0x0C, // Char 125 (})
0x00, 0x00, 0x00, 0x4C, 0x32, 0x00, 0x00, 0x00 // Char 126 (~)
};
void gfx_init_ctxt(gfx_ctxt_t *ctxt, u32 *fb, u32 width, u32 height, u32 stride)
{
ctxt->fb = fb;
ctxt->width = width;
ctxt->height = height;
ctxt->stride = stride;
}
void gfx_clear_grey(gfx_ctxt_t *ctxt, u8 color)
{
memset(ctxt->fb, color, 0x3C0000);
}
void gfx_clear_color(gfx_ctxt_t *ctxt, u32 color)
{
for (u32 i = 0; i < ctxt->height * ctxt->stride; i++)
ctxt->fb[i] = color;
}
void gfx_clear_partial_grey(gfx_ctxt_t *ctxt, u8 color, u32 pos_x, u32 height)
{
memset(ctxt->fb + pos_x * ctxt->stride, color, height * 4 * ctxt->stride);
}
void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt)
{
con->gfx_ctxt = ctxt;
con->fntsz = 16;
con->x = 0;
con->y = 0;
con->savedx = 0;
con->savedy = 0;
con->fgcol = 0xFFCCCCCC;
con->fillbg = 0;
con->bgcol = 0xFF1B1B1B;
con->mute = 0;
}
void gfx_con_setcol(gfx_con_t *con, u32 fgcol, int fillbg, u32 bgcol)
{
con->fgcol = fgcol;
con->fillbg = fillbg;
con->bgcol = bgcol;
}
void gfx_con_getpos(gfx_con_t *con, u32 *x, u32 *y)
{
*x = con->x;
*y = con->y;
}
void gfx_con_setpos(gfx_con_t *con, u32 x, u32 y)
{
con->x = x;
con->y = y;
}
void gfx_putc(gfx_con_t *con, char c)
{
// Duplicate code for performance reasons.
switch (con->fntsz)
{
case 16:
if (c >= 32 && c <= 126)
{
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
u32 *fb = con->gfx_ctxt->fb + con->x + con->y * con->gfx_ctxt->stride;
for (u32 i = 0; i < 16; i+=2)
{
u8 v = *cbuf++;
for (u32 k = 0; k < 2; k++)
{
for (u32 j = 0; j < 8; j++)
{
if (v & 1)
{
*fb = con->fgcol;
fb++;
*fb = con->fgcol;
}
else if (con->fillbg)
{
*fb = con->bgcol;
fb++;
*fb = con->bgcol;
}
else
fb++;
v >>= 1;
fb++;
}
fb += con->gfx_ctxt->stride - 16;
v = *cbuf;
}
}
con->x += 16;
}
else if (c == '\n')
{
con->x = 0;
con->y +=16;
if (con->y > con->gfx_ctxt->height - 16)
con->y = 0;
}
break;
case 8:
default:
if (c >= 32 && c <= 126)
{
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
u32 *fb = con->gfx_ctxt->fb + con->x + con->y * con->gfx_ctxt->stride;
for (u32 i = 0; i < 8; i++)
{
u8 v = *cbuf++;
for (u32 j = 0; j < 8; j++)
{
if (v & 1)
*fb = con->fgcol;
else if (con->fillbg)
*fb = con->bgcol;
v >>= 1;
fb++;
}
fb += con->gfx_ctxt->stride - 8;
}
con->x += 8;
}
else if (c == '\n')
{
con->x = 0;
con->y += 8;
if (con->y > con->gfx_ctxt->height - 8)
con->y = 0;
}
break;
}
}
void gfx_puts(gfx_con_t *con, const char *s)
{
if (!s || con->mute)
return;
for (; *s; s++)
gfx_putc(con, *s);
}
static void _gfx_putn(gfx_con_t *con, u32 v, int base, char fill, int fcnt)
{
char buf[65];
static const char digits[] = "0123456789ABCDEFghijklmnopqrstuvwxyz";
char *p;
int c = fcnt;
if (base > 36)
return;
p = buf + 64;
*p = 0;
do
{
c--;
*--p = digits[v % base];
v /= base;
} while (v);
if (fill != 0)
{
while (c > 0)
{
*--p = fill;
c--;
}
}
gfx_puts(con, p);
}
void gfx_put_small_sep(gfx_con_t *con)
{
u8 prevFontSize = con->fntsz;
con->fntsz = 8;
gfx_putc(con, '\n');
con->fntsz = prevFontSize;
}
void gfx_put_big_sep(gfx_con_t *con)
{
u8 prevFontSize = con->fntsz;
con->fntsz = 16;
gfx_putc(con, '\n');
con->fntsz = prevFontSize;
}
void gfx_printf(gfx_con_t *con, const char *fmt, ...)
{
if (con->mute)
return;
va_list ap;
int fill, fcnt;
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':
gfx_putc(con, va_arg(ap, u32));
break;
case 's':
gfx_puts(con, va_arg(ap, char *));
break;
case 'd':
_gfx_putn(con, va_arg(ap, u32), 10, fill, fcnt);
break;
case 'p':
case 'P':
case 'x':
case 'X':
_gfx_putn(con, va_arg(ap, u32), 16, fill, fcnt);
break;
case 'k':
con->fgcol = va_arg(ap, u32);
break;
case 'K':
con->bgcol = va_arg(ap, u32);
con->fillbg = 1;
break;
case '%':
gfx_putc(con, '%');
break;
case '\0':
goto out;
default:
gfx_putc(con, '%');
gfx_putc(con, *fmt);
break;
}
}
else
gfx_putc(con, *fmt);
fmt++;
}
out:
va_end(ap);
}
void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len)
{
if (con->mute)
return;
u8 prevFontSize = con->fntsz;
con->fntsz = 8;
for(u32 i = 0; i < len; i++)
{
if(i % 0x10 == 0)
{
if(i != 0)
{
gfx_puts(con, "| ");
for(u32 j = 0; j < 0x10; j++)
{
u8 c = buf[i - 0x10 + j];
if(c >= 32 && c <= 126)
gfx_putc(con, c);
else
gfx_putc(con, '.');
}
gfx_putc(con, '\n');
}
gfx_printf(con, "%08x: ", base + i);
}
gfx_printf(con, "%02x ", buf[i]);
if (i == len - 1)
{
int ln = len % 0x10 != 0;
u32 k = 0x10 - 1;
if (ln)
{
k = (len & 0xF) - 1;
for (u32 j = 0; j < 0x10 - k; j++)
gfx_puts(con, " ");
}
gfx_puts(con, "| ");
for(u32 j = 0; j < (ln ? k : k + 1); j++)
{
u8 c = buf[i - k + j];
if(c >= 32 && c <= 126)
gfx_putc(con, c);
else
gfx_putc(con, '.');
}
gfx_putc(con, '\n');
}
}
gfx_putc(con, '\n');
con->fntsz = prevFontSize;
}
static int abs(int x)
{
if (x < 0)
return -x;
return x;
}
void gfx_set_pixel(gfx_ctxt_t *ctxt, u32 x, u32 y, u32 color)
{
ctxt->fb[x + y * ctxt->stride] = color;
}
void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color)
{
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = (dx > dy ? dx : -dy) / 2, e2;
while (1)
{
gfx_set_pixel(ctxt, x0, y0, color);
if (x0 == x1 && y0 == y1)
break;
e2 = err;
if (e2 >-dx)
{
err -= dy;
x0 += sx;
}
if (e2 < dy)
{
err += dx;
y0 += sy;
}
}
}
void gfx_set_rect_grey(gfx_ctxt_t *ctxt, const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
{
u32 pos = 0;
for (u32 y = pos_y; y < (pos_y + size_y); y++)
{
for (u32 x = pos_x; x < (pos_x + size_x); x++)
{
memset(&ctxt->fb[x + y*ctxt->stride], buf[pos], 4);
pos++;
}
}
}
void gfx_set_rect_rgb(gfx_ctxt_t *ctxt, const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
{
u32 pos = 0;
for (u32 y = pos_y; y < (pos_y + size_y); y++)
{
for (u32 x = pos_x; x < (pos_x + size_x); x++)
{
ctxt->fb[x + y*ctxt->stride] = buf[pos + 2] | (buf[pos + 1] << 8) | (buf[pos] << 16);
pos+=3;
}
}
}
void gfx_set_rect_argb(gfx_ctxt_t *ctxt, const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
{
u32 *ptr = (u32 *)buf;
for (u32 y = pos_y; y < (pos_y + size_y); y++)
for (u32 x = pos_x; x < (pos_x + size_x); x++)
ctxt->fb[x + y * ctxt->stride] = *ptr++;
}
void gfx_render_bmp_argb(gfx_ctxt_t *ctxt, const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
{
for (u32 y = pos_y; y < (pos_y + size_y); y++)
{
for (u32 x = pos_x; x < (pos_x + size_x); x++)
ctxt->fb[x + y * ctxt->stride] = buf[(size_y + pos_y - 1 - y ) * size_x + x - pos_x];
}
}

55
ipl/gfx.h → bootloader/gfx/gfx.h Executable file → Normal file
View File

@@ -1,46 +1,25 @@
/*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
* Copyright (C) 2018 CTCaer
* Copyright (C) 2018 M4xw
*
* 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 _GFX_H_
#define _GFX_H_
#include "types.h"
typedef struct _gfx_ctxt_t
{
u32 *fb;
u32 width;
u32 height;
u32 stride;
} gfx_ctxt_t;
typedef struct _gfx_con_t
{
gfx_ctxt_t *gfx_ctxt;
u32 fntsz;
u32 x;
u32 y;
u32 savedx;
u32 savedy;
u32 fgcol;
int fillbg;
u32 bgcol;
int mute;
} gfx_con_t;
#include "../../common/common_gfx.h"
void gfx_init_ctxt(gfx_ctxt_t *ctxt, u32 *fb, u32 width, u32 height, u32 stride);
void gfx_clear_grey(gfx_ctxt_t *ctxt, u8 color);

931
bootloader/gfx/logos.h Normal file
View File

@@ -0,0 +1,931 @@
/*
* 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 _HEKATE_LOGOS_H_
#define _HEKATE_LOGOS_H_
#ifdef MENU_LOGO_ENABLE
// 119 x 57 @24bpp RGB RAW positioned at 577 x 1199
#define SZ_MENU_LOGO 20349
#define SZ_MENU_LOGO_BLZ 7592
static unsigned char Kc_MENU_LOGO_blz[SZ_MENU_LOGO_BLZ] = {
0x01, 0x10, 0x80, 0x2D, 0xF0, 0x99, 0x30, 0x84, 0xB0, 0x1C, 0x6C, 0x60, 0x51, 0xF0, 0x59, 0x31,
0x03, 0x30, 0xF7, 0x0F, 0xF0, 0x0F, 0xF0, 0x42, 0xF0, 0xFE, 0xF4, 0x15, 0x6C, 0xCF, 0x30, 0xCC,
0x20, 0x1D, 0x7F, 0x1F, 0x52, 0x6D, 0xD8, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0xC9, 0xF0, 0xBE, 0xF2, 0x2A, 0x00, 0x75, 0x1F,
0x5D, 0x10, 0x36, 0x7F, 0x84, 0x10, 0x7E, 0x00, 0x85, 0x0B, 0x72, 0x00, 0x6C, 0x00, 0x54, 0x40,
0x1A, 0x42, 0x8F, 0xBF, 0x21, 0xCF, 0x1F, 0x33, 0x00, 0x03, 0x20, 0x0F, 0xF0, 0x09, 0x90, 0x03,
0x30, 0x00, 0x00, 0xFE, 0x33, 0x20, 0x9E, 0x01, 0x2D, 0x19, 0xF0, 0x10, 0x20, 0x49, 0x02, 0x30,
0x60, 0xD3, 0x08, 0x81, 0x23, 0x19, 0x1B, 0x2B, 0x19, 0x1B, 0x33, 0x01, 0x18, 0x1B, 0x38, 0x18,
0x2B, 0x05, 0x1B, 0x36, 0x18, 0x10, 0xF6, 0x00, 0xDC, 0x1E, 0x20, 0xE1, 0x30, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFB, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xD8, 0xF0,
0x3A, 0xFE, 0xAE, 0x00, 0x43, 0x2B, 0xFF, 0x2F, 0x19, 0x1B, 0x4A, 0x15, 0x1C, 0x6A, 0x11, 0x00,
0x1D, 0x8A, 0x0E, 0x1E, 0xAD, 0x09, 0x1E, 0xB7, 0x00, 0x81, 0x00, 0x07, 0x1E, 0xA6, 0x0A, 0x1E,
0x87, 0x0F, 0x01, 0x1E, 0x60, 0x13, 0x1D, 0x3E, 0x17, 0xEC, 0x51, 0x51, 0x40, 0xC0, 0xB3, 0x01,
0x1C, 0x6D, 0x12, 0x1D, 0x96, 0x09, 0x80, 0x0F, 0xF0, 0xC1, 0x09, 0x90, 0x03, 0x30, 0x00, 0x00,
0x97, 0x0C, 0x94, 0x15, 0x80, 0x10, 0x27, 0x1E, 0x37, 0x17, 0x54, 0xA9, 0x1E, 0x8F, 0x1D, 0x1C,
0x37, 0x28, 0x17, 0x1C, 0x57, 0x13, 0x1C, 0x73, 0x11, 0x1D, 0x00, 0xA8, 0x09, 0xB3, 0x08, 0x1E,
0xB5, 0x08, 0x1E, 0xB1, 0x01, 0x09, 0x1E, 0x9F, 0x0C, 0x1E, 0x74, 0x10, 0x1D, 0x00, 0x53, 0x13,
0x1C, 0x31, 0x18, 0xD0, 0x02, 0x35, 0xF4, 0x0F, 0xF0, 0xE0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xDA, 0xF0, 0x35, 0xFD, 0xFF, 0x62, 0x04, 0xA6, 0x18, 0x7D,
0x10, 0x1D, 0xC6, 0x06, 0x1E, 0x03, 0xF4, 0x01, 0x2A, 0xF0, 0x20, 0xF1, 0x01, 0x20, 0xC1, 0x04,
0x07, 0x1E, 0xEC, 0x01, 0x2A, 0x1A, 0x08, 0x0D, 0xD8, 0x49, 0x40, 0x64, 0xC7, 0x52, 0x0F, 0xF0,
0x0F, 0xF0, 0x30, 0xF0, 0x1B, 0x00, 0x59, 0x13, 0xEC, 0x27, 0x9F, 0x17, 0x57, 0x30, 0x18, 0x1B,
0x51, 0x15, 0x1C, 0x98, 0x01, 0x0B, 0x1D, 0xBA, 0x03, 0xFB, 0xD8, 0xF0, 0x00, 0x20, 0xE5, 0x14,
0x03, 0x1F, 0xA4, 0x0B, 0x1E, 0x4B, 0x16, 0x1C, 0x00, 0xAE, 0x03, 0x1D, 0x65, 0x81, 0x0F, 0xF0,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFD, 0x0F, 0xF0, 0x0F, 0xF0, 0xDF, 0xF0, 0xE7,
0xF9, 0x2D, 0x18, 0x1B, 0x4E, 0x0F, 0x15, 0x1C, 0xA8, 0x09, 0x1E, 0xF7, 0x23, 0x14, 0x30, 0xF0,
0xC0, 0x0E, 0xA4, 0x99, 0x0C, 0x1E, 0x35, 0x93, 0x18, 0x62, 0x11, 0x47, 0x61, 0xE3, 0x0A, 0x4E,
0x50, 0x0F, 0xF0, 0x36, 0xF0, 0x62, 0xF1, 0x5F, 0x13, 0x1C, 0x1F, 0x36, 0x07, 0x19, 0xB5, 0x15,
0x1A, 0x07, 0x1B, 0x69, 0x11, 0x1C, 0x0D, 0xD0, 0xC1, 0x42, 0xD5, 0xF0, 0x9A, 0xA5, 0x6D, 0x11,
0x1D, 0x26, 0x0E, 0xDE, 0x00, 0x9C, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0xE7, 0xF0, 0xA4, 0xF7, 0xE6, 0x11, 0x09, 0x19, 0xBE, 0x08,
0x36, 0xA0, 0x9F, 0x2A, 0xF0, 0xE7, 0xAC, 0x0B, 0x1F, 0x2D, 0x19, 0x48, 0x10, 0x3A, 0x43, 0x17,
0x1C, 0xC3, 0x36, 0xB3, 0x0F, 0xF0, 0x2D, 0xF0, 0xD3, 0x95, 0xE2, 0x02, 0xF8, 0x11, 0x1D, 0x5B,
0x12, 0x31, 0x18, 0x1C, 0x72, 0x11, 0x04, 0x2C, 0xA1, 0x0C, 0xC0, 0xC0, 0xC0, 0xF4, 0x01, 0x20,
0x6C, 0x11, 0x07, 0xFA, 0x18, 0x1C, 0x62, 0xC1, 0x36, 0xF0, 0x0F, 0xF0, 0x23, 0xF0, 0x45, 0xF0,
0x35, 0xF1, 0xFD, 0x0F, 0xF0, 0x13, 0xF1, 0x11, 0xF1, 0x99, 0x03, 0xE5, 0x25, 0x3C, 0x00, 0x1E,
0xC0, 0xCF, 0x7F, 0x06, 0x1E, 0x99, 0x0B, 0x1E, 0x81, 0x0F, 0x1E, 0x00, 0x38, 0x04, 0xA1, 0x0B,
0x1E, 0xDA, 0x56, 0x27, 0x60, 0x90, 0x7C, 0x61, 0x10, 0x1D, 0x23, 0xCE, 0x21, 0xC3, 0x06, 0xA8,
0x27, 0x50, 0x1B, 0x30, 0xD8, 0xA7, 0x0A, 0x1E, 0xAA, 0x09, 0x1E, 0xE5, 0x03, 0x00, 0x20, 0xBE,
0x95, 0xB1, 0x09, 0x1F, 0x03, 0x00, 0xA4, 0x03, 0x30, 0xA2, 0x0A, 0x1E, 0x00, 0x00, 0x47, 0x04,
0x95, 0x0D, 0x1E, 0x36, 0x0C, 0x18, 0x1B, 0x16, 0xCF, 0x23, 0x5F, 0x13, 0x1D, 0xD7, 0x08, 0x33,
0x19, 0xC1, 0xA2, 0x2B, 0x02, 0x8D, 0x0E, 0x1E, 0x7E, 0x10, 0x07, 0x1E, 0x8C, 0x0E, 0x1E, 0xB8,
0x08, 0x1E, 0xED, 0x00, 0x81, 0x23, 0x3E, 0x9D, 0x45, 0x16, 0xCC, 0xF6, 0x1B, 0x3C, 0x90, 0x36,
0x60, 0xD3, 0x65, 0xF1, 0x2A, 0xF0, 0x33, 0xC0, 0xB1, 0xC9, 0x29, 0xF1, 0x96, 0x99, 0x15, 0x9C,
0x34, 0x75, 0xFF, 0xB9, 0x21, 0x2C, 0x19, 0x1B, 0x77, 0xD5, 0x0F, 0x77, 0x87, 0x64, 0x0E, 0xE1,
0x89, 0x0D, 0x1E, 0x14, 0x07, 0x1E, 0x81, 0x20, 0x1E, 0x66, 0x1F, 0xA8, 0x5C, 0x14, 0xAA, 0x0A,
0x1E, 0xFE, 0x5D, 0x80, 0xDA, 0x9D, 0x22, 0xA1, 0x21, 0x1A, 0xC3, 0x3F, 0x27, 0xA0, 0x25, 0x19,
0x1B, 0x41, 0x0C, 0x17, 0x1C, 0xCD, 0x54, 0x80, 0x86, 0x01, 0xF9, 0x00, 0x3E, 0x07, 0x1E, 0x78,
0x03, 0x20, 0x20, 0x9C, 0x3F, 0xDB, 0x19, 0x36, 0x49, 0x40, 0x17, 0x1C, 0x1D, 0xAD, 0x0A, 0xDB,
0xA0, 0xDB, 0x04, 0x69, 0x16, 0x06, 0x00, 0x1D, 0x64, 0xEE, 0x0E, 0xE5, 0x1E, 0xFB, 0x0A, 0x1B,
0x61, 0x13, 0x1D, 0xD2, 0x07, 0xDE, 0xB0, 0x7B, 0x03, 0x24, 0x1A, 0x1C, 0x19, 0x93, 0xE9, 0x77,
0x01, 0xC3, 0x36, 0x00, 0xC8, 0x31, 0x30, 0x00, 0x36, 0xC0, 0x33, 0xF0, 0x1B, 0x40, 0x82, 0x22,
0xA6, 0x02, 0xFF, 0x00, 0x00, 0x33, 0x90, 0xD3, 0x32, 0x2C, 0xF1, 0xB9, 0x6A, 0xB5, 0x32, 0x03,
0x00, 0x4D, 0x01, 0xFF, 0xA0, 0x02, 0x32, 0x01, 0xF9, 0x00, 0x04, 0x12, 0xC1, 0x25, 0x48, 0x16,
0x1C, 0x1F, 0xBC, 0x08, 0x8C, 0xA1, 0x97, 0x0D, 0x1E, 0x16, 0x54, 0xC0, 0x84, 0x27, 0x3F, 0x17,
0x1C, 0xC5, 0x06, 0x1F, 0x62, 0x91, 0x7B, 0x41, 0x0F, 0x1D, 0x1C, 0x0C, 0x20, 0x18, 0x27, 0x80,
0x17, 0xBC, 0x21, 0xA8, 0x3D, 0x62, 0xE1, 0x42, 0x16, 0xBE, 0x15, 0x17, 0x06, 0x50, 0x19, 0x52,
0x83, 0x81, 0x2A, 0xDB, 0x10, 0x6D, 0x12, 0x07, 0x75, 0x01, 0x1F, 0x54, 0x1D, 0x14, 0x1C, 0x11,
0x1C, 0x5F, 0x41, 0x29, 0x41, 0xD6, 0x2B, 0x66, 0x70, 0x13, 0x1D, 0xED, 0x43, 0x72, 0x20, 0xE0,
0x03, 0x1F, 0x08, 0x43, 0xFF, 0x03, 0x13, 0x52, 0xB2, 0x38, 0x7D, 0x01, 0x30, 0x30, 0x30, 0x1E,
0xE7, 0x09, 0x72, 0x00, 0x59, 0x59, 0x59, 0xA4, 0x01, 0x45, 0x45, 0x23, 0x45, 0x28, 0x0B, 0x39,
0x00, 0x69, 0x00, 0x36, 0x90, 0x7B, 0xF9, 0xA9, 0x02, 0x5C, 0x01, 0xFE, 0xF4, 0x02, 0x00, 0x00,
0x1E, 0x0F, 0xF5, 0x0A, 0x73, 0x05, 0x44, 0x01, 0xA3, 0x02, 0x1A, 0xC7, 0xFF, 0xC5, 0x3A, 0x00,
0x00, 0xBC, 0x0A, 0x44, 0x01, 0xE7, 0x00, 0x3A, 0x05, 0xE7, 0x00, 0xD0, 0x0E, 0xFF, 0x46, 0x46,
0x46, 0x9A, 0x02, 0xD2, 0x00, 0x1B, 0x00, 0x28, 0x19, 0x38, 0x1B, 0x67, 0x12, 0x1D, 0xEF, 0x02,
0xF3, 0xA6, 0x3B, 0x40, 0x18, 0x1C, 0x12, 0x51, 0x3F, 0x65, 0x61, 0xB2, 0x38, 0x19, 0x1B, 0x38,
0x85, 0x0F, 0x57, 0xA0, 0xAC, 0x09, 0x1E, 0x19, 0x1C, 0x04, 0x19, 0x2B, 0x2A, 0x90, 0x9D, 0x22,
0x3E, 0x62, 0xE1, 0x43, 0x16, 0x8F, 0x11, 0x97, 0x56, 0x14, 0xB4, 0x66, 0x86, 0x5D, 0x3E, 0x04,
0x9D, 0x0B, 0xF3, 0xA6, 0xA5, 0x4F, 0x0A, 0x1E, 0x3D, 0x6B, 0x1A, 0x9D, 0x65, 0xA8, 0x23, 0x35,
0x18, 0x34, 0x1C, 0xBD, 0x08, 0x1F, 0x13, 0x92, 0x61, 0x13, 0xFA, 0x12, 0x90, 0x19, 0x5B, 0x2E,
0x26, 0x04, 0x47, 0x04, 0x52, 0x52, 0x52, 0xA3, 0x0E, 0xA3, 0xA3, 0x85, 0x08, 0xA7, 0x01, 0x36,
0x00, 0x39, 0x00, 0x65, 0x01, 0x1B, 0x03, 0xFC, 0x55, 0x55, 0x55, 0x48, 0x00, 0x65, 0x01, 0x4C,
0xF3, 0x89, 0x01, 0x28, 0x78, 0x28, 0x28, 0xA3, 0x02, 0x18, 0x0F, 0x49, 0x05, 0xD2, 0x06, 0x20,
0x01, 0xD7, 0x0D, 0xFC, 0x45, 0x0C, 0x7D, 0x01, 0x30, 0x00, 0xB2, 0x02, 0xCA, 0x12, 0x84, 0x86,
0x62, 0x01, 0x69, 0x7F, 0x69, 0x69, 0x87, 0x09, 0xB9, 0x0A, 0x35, 0x35, 0x35, 0x6D, 0x0C, 0x6D,
0x6D, 0xBC, 0xBC, 0xBC, 0xCF, 0x03, 0x06, 0x0F, 0x4D, 0x01, 0xE0, 0x54, 0x54, 0x54, 0xC1, 0x02,
0xEF, 0x1D, 0x19, 0x1B, 0x8D, 0x18, 0x0E, 0xB1, 0x90, 0x21, 0x9A, 0x0C, 0x1E, 0x14, 0x2D, 0x00,
0x82, 0xEF, 0xFD, 0x11, 0x2D, 0x50, 0x15, 0x1C, 0xEF, 0x02, 0x27, 0x7F, 0x83, 0xC3, 0x08, 0x20,
0x6F, 0x00, 0x17, 0xE8, 0x35, 0x62, 0xF1, 0x62, 0xF1, 0xE8, 0xEF, 0xFD, 0x8A, 0x2C, 0x3E, 0x17,
0x1C, 0xC4, 0x35, 0x81, 0xF1, 0x0E, 0xC3, 0x57, 0x14, 0x9E, 0x3A, 0xAB, 0xF3, 0x46, 0x12, 0x92,
0x0D, 0x1D, 0x1C, 0x61, 0x95, 0x92, 0x0E, 0xD6, 0x0B, 0x1A, 0x1A, 0xC4, 0x02, 0x28, 0x49, 0x28,
0xB2, 0x08, 0xBC, 0x01, 0x55, 0x0B, 0x5F, 0x07, 0x9A, 0x9A, 0x9A, 0x1E, 0x03, 0x00, 0x75, 0x75,
0x75, 0xCC, 0x09, 0x5D, 0x00, 0xD4, 0xD4, 0x31, 0xD4, 0xEF, 0xEF, 0xEF, 0x84, 0x84, 0x84, 0x3B,
0x04, 0x80, 0x88, 0x05, 0x24, 0x63, 0x8A, 0x39, 0xE5, 0x02, 0xD4, 0x0D, 0xA1, 0xA1, 0xA1, 0x1F,
0xF2, 0xF2, 0xF2, 0xCA, 0xCA, 0xCA, 0xA6, 0x05, 0x00, 0x00, 0xC0, 0x78, 0x78, 0x78, 0x98, 0x98,
0x98, 0xE0, 0x0A, 0x70, 0x02, 0xC0, 0x37, 0x05, 0x3B, 0x01, 0x23, 0x04, 0x62, 0x31, 0x57, 0x09,
0xC3, 0x03, 0x68, 0x01, 0x87, 0x09, 0xFF, 0x4C, 0x4C, 0x4C, 0x97, 0x97, 0x97, 0x88, 0x02, 0x4F,
0x08, 0xC0, 0x87, 0x87, 0x87, 0x20, 0x01, 0xCC, 0x03, 0x2C, 0x01, 0xEA, 0x00, 0xA4, 0x01, 0xF8,
0x3B, 0x17, 0x1C, 0xB4, 0x81, 0x8F, 0xE6, 0x0D, 0x74, 0x11, 0x30, 0x1D, 0x16, 0x11, 0x3D, 0x84,
0xF0, 0x3A, 0x05, 0x19, 0x1C, 0x88, 0x1C, 0x0F, 0x1D, 0xAD, 0x0A, 0x1E, 0xA9, 0x0B, 0x7E, 0x10,
0x80, 0x82, 0x10, 0x1D, 0xE0, 0x01, 0x16, 0x03, 0x30, 0x62, 0xF1, 0x62, 0xF1, 0xE8, 0x25, 0xFB,
0xA5, 0x23, 0x5A, 0x13, 0x1C, 0xDF, 0xA5, 0x83, 0xD7, 0x43, 0x04, 0x1F, 0x38, 0x17, 0x25, 0x2B,
0x43, 0xF2, 0x62, 0x21, 0x4F, 0x70, 0x15, 0x1C, 0xA1, 0x0C, 0x1E, 0xAE, 0x0A, 0x1E, 0x00, 0xA8,
0x0B, 0x1E, 0xA5, 0x0B, 0x1E, 0x61, 0x14, 0x00, 0x08, 0x11, 0x22, 0x23, 0x23, 0x33, 0x33, 0x33,
0xCA, 0x05, 0x81, 0xBC, 0x01, 0x7C, 0x08, 0x29, 0x07, 0x72, 0x30, 0x95, 0x01, 0xDE, 0x36, 0x50,
0x07, 0x99, 0x7F, 0x99, 0x99, 0xFA, 0xFA, 0xFA, 0x34, 0x0B, 0x09, 0x00, 0xE8, 0x32, 0xE0, 0x2C,
0x37, 0x29, 0x04, 0x79, 0x05, 0xB6, 0xB6, 0xB6, 0x12, 0x0F, 0x76, 0x47, 0x76, 0x76, 0xA0, 0x02,
0x3D, 0x38, 0xA6, 0x32, 0x6F, 0x09, 0xDF, 0x02, 0x8A, 0x39, 0xFC, 0x35, 0x01, 0x46, 0x00, 0x21,
0x30, 0x2C, 0x2C, 0x2C, 0x62, 0x01, 0x43, 0x08, 0xC7, 0xA9, 0xA9, 0xA9, 0x73, 0x02, 0x70, 0x70,
0x70, 0x0C, 0x00, 0x88, 0x23, 0x01, 0xD3, 0x0E, 0xE1, 0x00, 0xE7, 0x00, 0x31, 0x02, 0x5B, 0x38,
0xC9, 0x57, 0x80, 0xBF, 0xF2, 0x02, 0x5A, 0x0F, 0x1C, 0x1C, 0x4E, 0xC8, 0xF4, 0xE5, 0x38, 0x44,
0x17, 0xF4, 0x81, 0x10, 0x24, 0xD3, 0x28, 0x1E, 0x2D, 0x70, 0x62, 0xF1, 0x62, 0xF1, 0xC7, 0xF2,
0xF5, 0x72, 0x1F, 0x71, 0x11, 0x1D, 0xF2, 0xC0, 0x89, 0xC2, 0x06, 0x21, 0x1F, 0x32, 0x5B, 0x28,
0x62, 0xF1, 0x47, 0x1A, 0xD7, 0x27, 0x23, 0x1C, 0x2B, 0xBC, 0x27, 0xCE, 0x07, 0x35, 0x0A, 0xFF,
0x06, 0x1C, 0x1C, 0x91, 0x08, 0x63, 0x4E, 0x63, 0x63, 0xF4, 0xF4, 0xF4, 0x9B, 0x01, 0x2B, 0x0B,
0x83, 0x01, 0xE0, 0x29, 0x94, 0x4B, 0x30, 0x0B, 0x04, 0xB0, 0xB0, 0xB0, 0x04, 0x0B, 0xAC, 0x05,
0xC7, 0x65, 0x01, 0x1E, 0x30, 0x29, 0x04, 0x33, 0x00, 0x96, 0x96, 0x96, 0xF6, 0x0F, 0xF6, 0xF6,
0x61, 0x61, 0x61, 0xC4, 0x02, 0x36, 0x60, 0x33, 0x60, 0xE0, 0x6E, 0x01, 0xA4, 0xA4, 0xA4, 0xF7,
0xF7, 0xF7, 0x38, 0x01, 0x81, 0x1B, 0x00, 0xBA, 0x39, 0x97, 0x02, 0x2B, 0x08, 0x00, 0x00, 0xB2,
0x02, 0x9C, 0x06, 0x4F, 0x02, 0xFF, 0xDE, 0x06, 0x5C, 0x61, 0xF6, 0x66, 0x49, 0x15, 0x47, 0xAA,
0xE2, 0x03, 0x27, 0x14, 0x0D, 0xB8, 0x55, 0x87, 0xF0, 0x1E, 0x30, 0x81, 0x80, 0x19, 0x1C, 0x5C,
0xB0, 0x9F, 0x62, 0xF1, 0x62, 0xF1, 0x43, 0xE5, 0x27, 0x1A, 0x7B, 0x0F, 0x1E, 0xF9, 0x27, 0x62,
0x81, 0xAC, 0x0A, 0x1E, 0x2A, 0x91, 0xA5, 0xE1, 0xF0, 0x03, 0x30, 0xE1, 0x00, 0x00, 0x3B, 0x11,
0x18, 0x62, 0x51, 0xB2, 0xB2, 0xB2, 0xCC, 0x0B, 0xCC, 0xCC, 0xC6, 0x09, 0x6F, 0x00, 0x0C, 0x30,
0xEF, 0xCD, 0x9E, 0x01, 0xB6, 0x01, 0xFC, 0xE7, 0xE7, 0xE7, 0xCD, 0x05, 0x2C, 0x04, 0xB0, 0x31,
0x0B, 0x04, 0x53, 0x78, 0x53, 0x53, 0x29, 0x04, 0x8A, 0x8A, 0x8A, 0x5A, 0x9F, 0x23, 0x61, 0xC4,
0x60, 0x3F, 0xE2, 0x02, 0xD8, 0xD8, 0xD8, 0xB9, 0xB9, 0xB9, 0x03, 0x35, 0x04, 0x29, 0x01, 0x55,
0x02, 0x62, 0x01, 0x03, 0x00, 0x62, 0x01, 0xDE, 0x06, 0x3E, 0x01, 0xFF, 0xEB, 0x6E, 0x62, 0xC1,
0x4B, 0x62, 0xB1, 0xDB, 0x05, 0x1F, 0x2E, 0x0B, 0x19, 0x1E, 0x10, 0x62, 0xF1, 0x81, 0xF0, 0x60,
0xF0, 0x62, 0xF1, 0x62, 0xF1, 0x62, 0xF1, 0xFE, 0xC7, 0xF2, 0xA2, 0x0C, 0x62, 0xE1, 0xA2, 0xF3,
0x23, 0x31, 0x32, 0x8A, 0x2F, 0x79, 0x2F, 0x2F, 0xAF, 0xAF, 0xAF, 0x72, 0x0F, 0x0E, 0x0E, 0x20,
0x0E, 0x75, 0x60, 0xE9, 0xCD, 0x86, 0x01, 0x4B, 0x4B, 0x4B, 0xD9, 0x0E, 0xD9, 0xD9, 0x91, 0x05,
0x62, 0x01, 0x50, 0x31, 0xFF, 0x03, 0x9B, 0x9B, 0x3C, 0x9B, 0xD6, 0xD6, 0xD6, 0x72, 0x0F, 0xBD,
0x39, 0x29, 0xC1, 0x73, 0x32, 0xF0, 0x02, 0x01, 0x54, 0x0C, 0xE5, 0xE5, 0xE5, 0x44, 0x44, 0x44,
0x03, 0x62, 0x31, 0x31, 0x31, 0x31, 0xAB, 0xAB, 0xAB, 0x43, 0x05, 0x81, 0x15, 0x0C, 0x03, 0x00,
0x15, 0x3C, 0x62, 0xF1, 0xD6, 0x0B, 0xE1, 0x62, 0x81, 0x8B, 0x0E, 0xDF, 0x2F, 0x62, 0x01, 0x62,
0xF1, 0x0F, 0xF0, 0x63, 0xF0, 0x62, 0xF1, 0x62, 0xF1, 0x62, 0xF1, 0xFE, 0x90, 0x1C, 0x1C, 0x8A,
0x62, 0xB1, 0xA4, 0x62, 0x51, 0x62, 0xF1, 0x9C, 0xF0, 0xE9, 0x49, 0x6E, 0x98, 0x01, 0x5A, 0x00,
0x71, 0x01, 0x65, 0x01, 0xBB, 0x32, 0x2C, 0xC7, 0xD2, 0x39, 0xFF, 0x40, 0x40, 0x40, 0xD3, 0xD3,
0xD3, 0xF6, 0x06, 0x12, 0x40, 0x12, 0x12, 0x62, 0x01, 0x12, 0x00, 0x97, 0x05, 0xD5, 0xD5, 0xD5,
0x1C, 0x94, 0x94, 0x94, 0x7E, 0x3C, 0x0F, 0x00, 0x8E, 0xC5, 0x00, 0x00, 0x34, 0x08, 0xF8, 0x0F,
0x00, 0x64, 0x64, 0x64, 0xED, 0x03, 0x6B, 0x6B, 0x6B, 0x11, 0x77, 0x31, 0x2D, 0x2D, 0x2D, 0xAA,
0xAA, 0xAA, 0x50, 0x01, 0x81, 0x3B, 0x3B, 0x3B, 0xEF, 0x27, 0x2B, 0xE0, 0x88, 0x28, 0x4A, 0x15,
0x38, 0x1C, 0xE0, 0x62, 0xB1, 0xD5, 0x0F, 0x86, 0xF4, 0x1B, 0x0F, 0xF0, 0x63, 0xF0, 0xDC, 0x62,
0xF1, 0x62, 0xF1, 0x62, 0xF1, 0xC1, 0x15, 0x1C, 0x89, 0x0E, 0x0D, 0xA5, 0x8F, 0xA3, 0x0B, 0x1E,
0x26, 0x1A, 0x9F, 0xD6, 0x0F, 0xF0, 0x90, 0xF0, 0xE0, 0x00, 0x00, 0x8F, 0x01, 0x17, 0x3A, 0x62,
0x04, 0xB8, 0x02, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7A, 0x01, 0x4A, 0x01, 0xA9, 0x02,
0x49, 0x49, 0x49, 0xF6, 0x06, 0xC5, 0x0D, 0xC7, 0x2C, 0x34, 0xC3, 0x09, 0x44, 0x01, 0xA3, 0x02,
0x66, 0x0F, 0x32, 0x32, 0x32, 0x1F, 0x38, 0x38, 0x38, 0x06, 0x60, 0x03, 0x30, 0x00, 0x00, 0xEF,
0x0A, 0xAD, 0x0D, 0xF8, 0xD0, 0x02, 0x56, 0x56, 0x56, 0xDB, 0xDB, 0xDB, 0x84, 0x0C, 0x81, 0x12,
0x00, 0x62, 0x61, 0x2C, 0x01, 0x62, 0x41, 0x62, 0xF1, 0xE5, 0x28, 0x47, 0x15, 0x3F, 0x1C, 0xD8,
0xF9, 0x76, 0xBB, 0x1B, 0x33, 0x20, 0x00, 0x24, 0x60, 0x5E, 0xF5, 0xEC, 0x84, 0x80, 0x3B, 0xE1,
0x62, 0xF1, 0x62, 0xF1, 0x62, 0xF1, 0xF9, 0x16, 0x80, 0x0F, 0x3F, 0x1D, 0xFD, 0x62, 0x81, 0xA6,
0xB1, 0x1C, 0x62, 0xE1, 0x01, 0xE5, 0x1F, 0x12, 0xF4, 0x51, 0x36, 0x59, 0x87, 0x03, 0x03, 0xFC,
0x09, 0xCC, 0x0C, 0x87, 0x0C, 0x13, 0x0B, 0x5D, 0x7F, 0x5D, 0x5D, 0x66, 0x66, 0x66, 0x00, 0x00,
0x00, 0x00, 0x68, 0x60, 0x68, 0x68, 0x6C, 0x6C, 0x6C, 0x64, 0x0B, 0x39, 0x0F, 0xAC, 0x02, 0xE0,
0x62, 0x31, 0xC7, 0x02, 0x72, 0x72, 0x72, 0xEE, 0xEE, 0xEE, 0x03, 0xE1, 0x06, 0xC2, 0xC2, 0xC2,
0x00, 0x00, 0x09, 0x90, 0x03, 0x30, 0x00, 0x00, 0xF1, 0xC4, 0xC4, 0xC4, 0xC6, 0xC6, 0xC6, 0x51,
0x0C, 0xF3, 0x40, 0xF3, 0xF3, 0xFC, 0x03, 0xE1, 0x33, 0x62, 0xD1, 0x62, 0xF1, 0xBA, 0x20, 0x69,
0x00, 0xFC, 0xCC, 0x57, 0x80, 0xEB, 0x03, 0x20, 0x4F, 0x08, 0x2F, 0x84, 0x81, 0xF0, 0xE2, 0x09,
0x10, 0x21, 0x84, 0x50, 0x1F, 0x1A, 0x1B, 0x1D, 0x5A, 0x90, 0x85, 0x62, 0xF1, 0x62, 0xF1, 0x94,
0xC5, 0x70, 0x22, 0x74, 0x10, 0x1D, 0xF5, 0x0F, 0x43, 0x82, 0xB8, 0x08, 0x1E, 0x2F, 0x18, 0x1C,
0x89, 0x8D, 0x81, 0x63, 0xFC, 0x71, 0x21, 0x54, 0x46, 0xFA, 0x6E, 0x5F, 0x11, 0x14, 0x07, 0x3C,
0x3C, 0x3F, 0x3C, 0x6B, 0x01, 0xA5, 0x0C, 0xDA, 0xDA, 0xDA, 0x77, 0x01, 0x00, 0x00, 0xC6, 0x03,
0x30, 0x22, 0x3E, 0xC0, 0x0C, 0x5B, 0x08, 0xEF, 0x0D, 0xC7, 0x32, 0x46, 0x08, 0x5E, 0x05, 0xFF,
0xE4, 0x06, 0xB1, 0xB1, 0xB1, 0xA5, 0xA5, 0xA5, 0xA6, 0x01, 0xA6, 0xA6, 0x00, 0x00, 0x09, 0x90,
0x03, 0x30, 0x00, 0x00, 0x12, 0x00, 0xE3, 0x0A, 0xFC, 0x95, 0x95, 0x95, 0xCC, 0x03, 0xC0, 0x69,
0x62, 0xF1, 0x2D, 0xF0, 0x3C, 0x78, 0x18, 0x1C, 0xC3, 0x07, 0x57, 0x70, 0x9B, 0x07, 0x6A, 0x12,
0x30, 0x1D, 0x9F, 0x3F, 0x1B, 0x20, 0xFA, 0x64, 0x25, 0x3D, 0x18, 0x87, 0x00, 0x9A, 0x81, 0x10,
0x41, 0x16, 0x1C, 0x2D, 0x18, 0x1B, 0x23, 0x01, 0x59, 0x60, 0x62, 0xF1, 0x62, 0xF1, 0x2C, 0xF4,
0xA8, 0x23, 0x67, 0x11, 0x1D, 0x1F, 0xEE, 0x20, 0x87, 0xCD, 0x05, 0x1F, 0x3A, 0x18, 0x1C, 0x02,
0xDE, 0x10, 0xAD, 0xF0, 0xAD, 0x07, 0x1A, 0xAB, 0x00, 0x61, 0x15, 0x4E, 0x15, 0x37, 0x1C, 0xD2,
0x00, 0x38, 0x18, 0x1C, 0x27, 0x19, 0xE9, 0x14, 0x82, 0x50, 0x04, 0x2D, 0x2E, 0x2E, 0x12, 0x00,
0x6C, 0x00, 0xF9, 0xF9, 0x31, 0xF9, 0xD5, 0x0C, 0x18, 0x00, 0x64, 0x0B, 0x09, 0x00, 0x03, 0x00,
0x58, 0x58, 0x3E, 0x58, 0xBD, 0x09, 0x5B, 0x5B, 0x5B, 0x6E, 0x6E, 0x6E, 0x02, 0xDD, 0xDD, 0xDD,
0xBA, 0x09, 0xC7, 0x32, 0x2E, 0x08, 0x7F, 0x7F, 0x38, 0x7F, 0xDC, 0xDC, 0xDC, 0x07, 0x0E, 0x1E,
0x1E, 0x1E, 0x10, 0x1B, 0x00, 0x00, 0x00, 0x09, 0x90, 0x03, 0x30, 0x00, 0x00, 0xDE, 0x06, 0xFF,
0x03, 0x15, 0x00, 0xFF, 0x8E, 0x35, 0x62, 0x11, 0x62, 0xF1, 0x50, 0xFA, 0x83, 0x17, 0x1B, 0xDD,
0xC4, 0xAF, 0x0B, 0xDF, 0x18, 0x84, 0x20, 0x1A, 0xD7, 0xED, 0x24, 0x1A, 0x1B, 0x4B, 0x0A, 0x15,
0x1C, 0xC4, 0x07, 0x1E, 0xEA, 0x87, 0x20, 0xF0, 0x40, 0x02, 0x1F, 0xB3, 0x09, 0x1E, 0x2C, 0x1A,
0x1B, 0x00, 0x15, 0x62, 0x81, 0x62, 0xF1, 0x62, 0xF1, 0x62, 0xF1, 0x4A, 0x16, 0x1C, 0x1E, 0xD5,
0xF4, 0x82, 0xE8, 0x02, 0x20, 0x48, 0xFD, 0x07, 0x7D, 0x0D, 0xC2, 0x7B, 0xF3, 0xB0, 0x27, 0x79,
0x0F, 0x1D, 0xE0, 0x04, 0x1F, 0x03, 0xE8, 0x02, 0x1F, 0x54, 0x06, 0xB4, 0x09, 0x85, 0x0E, 0x1C,
0x18, 0x1E, 0x1E, 0x1D, 0x29, 0x2A, 0x2A, 0x5B, 0x5C, 0x00, 0x5C, 0x98, 0x01, 0x31, 0x0B, 0x8B,
0x05, 0x24, 0x00, 0xD5, 0x0C, 0xAF, 0x38, 0x00, 0x00, 0xFE, 0x65, 0x01, 0x50, 0x01, 0x6B, 0x04,
0x7B, 0x0C, 0xC3, 0x09, 0x62, 0x31, 0x0F, 0x00, 0x3A, 0x08, 0xFF, 0x71, 0x71, 0x71, 0xE4, 0x09,
0x59, 0x59, 0x59, 0x62, 0x01, 0x88, 0x1A, 0x04, 0x00, 0x00, 0x09, 0x90, 0x20, 0x91, 0xC7, 0xF2,
0x62, 0xF1, 0xC7, 0xF2, 0xB6, 0x07, 0xFF, 0x7A, 0x10, 0x1D, 0xFE, 0x79, 0x88, 0xB4, 0x08, 0x1E,
0x10, 0x27, 0x19, 0x26, 0xBD, 0x75, 0x5C, 0x2F, 0x19, 0x1B, 0x72, 0x0C, 0x11, 0x1D, 0xF7, 0xAD,
0x74, 0x21, 0xBE, 0x08, 0x1F, 0x08, 0x1E, 0x1B, 0x4F, 0x58, 0x62, 0xF1, 0x62, 0xF1, 0x35, 0xF1,
0xE0, 0x27, 0x30, 0x7C, 0x19, 0x1C, 0xB7, 0x08, 0x2A, 0xA0, 0x69, 0x06, 0x20, 0x1A, 0x30, 0x09,
0x20, 0xEE, 0xBB, 0x1E, 0x8C, 0x1A, 0x1C, 0xB2, 0x09, 0x7E, 0xA3, 0x8B, 0x7F, 0x0E, 0x1B, 0x20,
0x23, 0x22, 0x3F, 0x41, 0x00, 0x41, 0xC1, 0xC1, 0xC1, 0xE4, 0xE4, 0xE4, 0x92, 0x01, 0x80, 0x0F,
0x0F, 0x0F, 0x50, 0x07, 0x33, 0x00, 0x03, 0x30, 0x53, 0x31, 0xDC, 0x35, 0xF8, 0x3F, 0x3F, 0x3F,
0xD2, 0xD2, 0xD2, 0x92, 0x92, 0x00, 0x92, 0x62, 0x31, 0x67, 0x05, 0x62, 0x62, 0x62, 0x8E, 0x02,
0x8A, 0x09, 0xC6, 0x60, 0x3C, 0x0C, 0xC0, 0xA7, 0xFD, 0x62, 0x71, 0x62, 0xF1, 0xE9, 0xF1, 0x07,
0x22, 0x50, 0x7F, 0x15, 0x1D, 0x4A, 0x04, 0xBC, 0x94, 0x64, 0x12, 0x1D, 0x1D, 0x0C, 0x8D, 0xBC,
0x19, 0xD8, 0x26, 0x40, 0x16, 0x1C, 0xAD, 0x08, 0x05, 0x38, 0xA1, 0x95, 0x0C, 0x1E, 0x16, 0x2A,
0x90, 0x62, 0xF1, 0x62, 0xF1, 0xE1, 0x4B, 0xF9, 0x1C, 0x1B, 0x26, 0xCA, 0x02, 0x0F, 0x1D, 0xFC,
0x11, 0xDE, 0x80, 0xC8, 0x06, 0x1F, 0x3A, 0x17, 0x1B, 0x1E, 0x01, 0x1A, 0x1B, 0x19, 0x00, 0xBC,
0x2B, 0x19, 0x1B, 0x5C, 0x08, 0x13, 0x1C, 0xD6, 0x19, 0x82, 0xF2, 0x01, 0x1F, 0x46, 0x08, 0x14,
0x62, 0x11, 0x5B, 0x5D, 0x5D, 0x03, 0x03, 0x7A, 0x7A, 0x22, 0x7A, 0x89, 0x01, 0x00, 0x00, 0x0F,
0x00, 0x4C, 0xFB, 0x53, 0x04, 0xB5, 0x05, 0xD1, 0x7E, 0xD1, 0xD1, 0x91, 0x05, 0x05, 0x0A, 0x3B,
0x01, 0xCA, 0x02, 0x43, 0x43, 0x3C, 0x43, 0xD4, 0xD4, 0xD4, 0x9C, 0x9C, 0x9C, 0x38, 0x34, 0x80,
0x36, 0xC0, 0x37, 0xFB, 0x62, 0xC1, 0x62, 0xF1, 0x86, 0xF7, 0x2D, 0x19, 0x1B, 0x1F, 0x9A, 0x0C,
0x84, 0xA0, 0xD2, 0x05, 0x1F, 0x58, 0x14, 0x04, 0x1D, 0x28, 0x03, 0x10, 0x84, 0x00, 0x79, 0x05,
0xC5, 0x11, 0x3D, 0x17, 0x3C, 0x1B, 0x7B, 0x0F, 0x1D, 0xEA, 0x5F, 0x81, 0xF2, 0x02, 0x20, 0x20,
0x55, 0x15, 0x1C, 0x18, 0x2A, 0x90, 0x62, 0xF1, 0x62, 0xF1, 0xE0, 0x97, 0xF2, 0x2E, 0x28, 0x42,
0x16, 0x1C, 0xD4, 0x05, 0x24, 0xA0, 0x83, 0xA5, 0x0B, 0x1E, 0x39, 0x18, 0xAE, 0x16, 0x20, 0xF1,
0x08, 0xA0, 0x1A, 0x1B, 0x25, 0x1A, 0x1B, 0x2E, 0x19, 0x1C, 0x00, 0x4C, 0x15, 0x1C, 0xA6, 0xA3,
0xB2, 0xBD, 0x07, 0x1E, 0x10, 0x2D, 0x16, 0x1A, 0x23, 0x28, 0x27, 0x79, 0x7A, 0x00, 0x7A, 0x62,
0x01, 0x1E, 0x00, 0x15, 0x00, 0x1D, 0x37, 0xA8, 0xF9, 0xC1, 0x02, 0x5E, 0x7E, 0x5E, 0x5E, 0xED,
0xED, 0xED, 0x8F, 0x8F, 0x8F, 0x00, 0x62, 0x01, 0xDB, 0x09, 0x36, 0x00, 0x44, 0x04, 0x38, 0x04,
0x8B, 0x02, 0x46, 0x46, 0x3F, 0x46, 0x7E, 0x69, 0xA8, 0xF9, 0xBB, 0x32, 0xF6, 0x36, 0x62, 0x71,
0x62, 0xF1, 0x81, 0xF0, 0xFE, 0x51, 0x20, 0x4D, 0x15, 0x1C, 0xD9, 0x05, 0xCD, 0xA2, 0xF2, 0x01,
0xC1, 0x84, 0x0E, 0x1E, 0x8A, 0x00, 0x53, 0x15, 0x1C, 0x58, 0x08, 0x14, 0x1C, 0x78, 0x00, 0x9A,
0x0B, 0x1E, 0xE6, 0x02, 0x04, 0x84, 0xA0, 0xBB, 0x05, 0x23, 0x1A, 0x6E, 0xF7, 0x1B, 0xC7, 0xF2,
0x62, 0xF1, 0xD3, 0xDE, 0xF0, 0x29, 0x1A, 0x1B, 0x7E, 0x10, 0x1D, 0x24, 0x90, 0x81, 0xFE, 0x00,
0x20, 0xB5, 0x08, 0x1E, 0x6F, 0x10, 0x00, 0x1D, 0x57, 0x14, 0x1C, 0x52, 0x15, 0x1C, 0x90, 0x03,
0x80, 0x7D, 0x0F, 0x1D, 0xB6, 0x09, 0x5C, 0xD1, 0x69, 0x10, 0x20, 0x1C, 0x11, 0x1A, 0x19, 0x24,
0x26, 0x26, 0x6D, 0x00, 0x6E, 0x6E, 0xE6, 0xE6, 0xE6, 0x89, 0x04, 0x63, 0x00, 0x24, 0x00, 0xE0,
0x3C, 0x60, 0x88, 0x68, 0x89, 0x01, 0x39, 0x39, 0x39, 0x53, 0x04, 0xA3, 0x02, 0xC7, 0x87, 0x87,
0x87, 0x62, 0x91, 0x50, 0x50, 0x50, 0xEB, 0x08, 0xEB, 0xEB, 0x26, 0x01, 0x18, 0x60, 0x7B, 0x99,
0x5B, 0x35, 0x3E, 0x01, 0x7B, 0x3F, 0xFC, 0x93, 0x36, 0x62, 0x91, 0x62, 0xF1, 0x35, 0xF4, 0x23,
0x1B, 0x1B, 0x6C, 0x0F, 0x12, 0x1D, 0xF6, 0x18, 0xB0, 0xFC, 0x00, 0x20, 0xE4, 0x08, 0x03, 0x1F,
0xD7, 0x04, 0x1F, 0xDA, 0x04, 0x1F, 0x00, 0xED, 0x84, 0xE0, 0xD8, 0x05, 0x1F, 0x80, 0x01, 0xEE,
0x44, 0xC7, 0xF2, 0xE2, 0xD9, 0x05, 0x62, 0xE1, 0x44, 0x62, 0xB1, 0xDE, 0xF0, 0x32, 0x18, 0x1C,
0x1B, 0xA5, 0x0A, 0x65, 0xD1, 0xF4, 0xAE, 0x23, 0xD6, 0x04, 0x1F, 0x14, 0xDC, 0x04, 0x1F, 0xF8,
0x01, 0xC6, 0xD0, 0xA1, 0x0B, 0x20, 0x1E, 0x21, 0x4A, 0x07, 0x1A, 0x19, 0x1B, 0x00, 0xE2, 0x05,
0xEA, 0x64, 0xEA, 0xEA, 0x9E, 0x01, 0x26, 0x26, 0x26, 0x23, 0x04, 0x00, 0x00, 0xC4, 0xEE, 0x62,
0x3C, 0x00, 0x44, 0x01, 0x2C, 0x04, 0x83, 0x83, 0x83, 0x9E, 0x01, 0x8F, 0xF4, 0xF4, 0xF4, 0x61,
0x0E, 0xCA, 0x02, 0x12, 0x33, 0x2D, 0x00, 0x38, 0x01, 0xF8, 0x89, 0x89, 0x89, 0xFE, 0xFE, 0xFE,
0x97, 0x02, 0x29, 0x01, 0xC0, 0xA0, 0x05, 0x1E, 0x00, 0xD5, 0x63, 0x44, 0x01, 0x12, 0x00, 0x41,
0x01, 0x81, 0x81, 0x3F, 0x81, 0x7C, 0x7C, 0x7C, 0x5E, 0x02, 0x62, 0xA1, 0x62, 0xF1, 0x65, 0xF1,
0xF0, 0x84, 0x20, 0x4D, 0x04, 0x77, 0x10, 0x1D, 0xEE, 0x02, 0x1F, 0x03, 0x0F, 0xF0, 0x6F, 0xF0,
0xDB, 0x04, 0x1F, 0x49, 0x17, 0x1C, 0x03, 0x16, 0x5F, 0x31, 0x62, 0xF1, 0x7F, 0x22, 0x3F, 0x17,
0x1C, 0xCF, 0x0E, 0x06, 0x1F, 0x33, 0x60, 0xEE, 0x02, 0x20, 0x43, 0x16, 0x04, 0x62, 0x81, 0xD4,
0xF0, 0x2C, 0x21, 0x36, 0x18, 0x1C, 0xA9, 0x09, 0x07, 0x1E, 0x00, 0x00, 0x0F, 0xF0, 0xD2, 0xF0,
0xA8, 0x0B, 0x1E, 0x28, 0x0E, 0x19, 0x1B, 0x18, 0x39, 0x23, 0x8A, 0x0E, 0x89, 0x01, 0x91, 0x91,
0x38, 0x91, 0xFF, 0xFF, 0xFF, 0x68, 0x01, 0x36, 0x36, 0x36, 0x10, 0x06, 0x00, 0x3F, 0x00, 0x24,
0x24, 0x24, 0x3C, 0x00, 0x37, 0x37, 0x23, 0x37, 0x57, 0x57, 0x57, 0x47, 0x01, 0xE5, 0xE5, 0xE5,
0x10, 0x90, 0x90, 0x90, 0xCE, 0xCE, 0xCE, 0x7A, 0x01, 0x4B, 0x00, 0xC0, 0x85, 0x65, 0x8B, 0x0B,
0x65, 0x01, 0x9F, 0x9F, 0x9F, 0xFB, 0xFB, 0x07, 0xFB, 0x99, 0x99, 0x99, 0x45, 0x45, 0x45, 0xA9,
0x02, 0x80, 0x6D, 0x0B, 0xEE, 0x02, 0x76, 0x02, 0x0B, 0x01, 0x51, 0x51, 0x51, 0xA1, 0x0F, 0xA1,
0xA1, 0xE7, 0xE7, 0xE7, 0x6D, 0x6D, 0x6D, 0x00, 0x19, 0x0E, 0x74, 0x01, 0x32, 0x01, 0x2A, 0x2A,
0x2A, 0x47, 0x01, 0xC5, 0x47, 0xC5, 0xC5, 0xFF, 0x03, 0xF9, 0x03, 0x62, 0xA1, 0x65, 0xF1, 0xEC,
0x21, 0x22, 0x7C, 0x1A, 0x1B, 0x5D, 0x13, 0x1C, 0xC7, 0x07, 0x1F, 0x00, 0xFD, 0x84, 0x50, 0x81,
0xF0, 0xF8, 0x01, 0x20, 0xAB, 0x0A, 0x06, 0x1E, 0x3C, 0x17, 0x92, 0x04, 0x5F, 0x51, 0xAA, 0xF4,
0x36, 0x20, 0x33, 0x78, 0x18, 0x1C, 0xC9, 0x06, 0x3C, 0x00, 0x22, 0x39, 0x20, 0x21, 0x50, 0xEC,
0x02, 0x21, 0x3B, 0x17, 0x1C, 0x1A, 0x71, 0x64, 0x80, 0xD4, 0xF0, 0xE1, 0x10, 0xA3, 0x12, 0x30,
0x18, 0x1B, 0x87, 0x0F, 0x07, 0x1E, 0xE1, 0x04, 0x1F, 0x0F, 0x60, 0x03, 0x30, 0x00, 0x00, 0x03,
0x00, 0xF0, 0xFF, 0x00, 0x21, 0xFF, 0x00, 0x20, 0xE3, 0x03, 0x00, 0x1F, 0x05, 0x01, 0x27, 0x1A,
0x1C, 0x17, 0x37, 0x22, 0x1A, 0x42, 0xA4, 0x51, 0x31, 0x31, 0x31, 0x23, 0x0D, 0xFC, 0xFC, 0xFC,
0x11, 0xCC, 0xCC, 0xCC, 0x8A, 0x8A, 0x8A, 0x76, 0x76, 0x00, 0x76, 0x78, 0x78, 0x78, 0x85, 0x85,
0x85, 0xB5, 0x00, 0xB5, 0xB5, 0x56, 0x01, 0xD6, 0xD6, 0xD6, 0x9D, 0x0B, 0x2B, 0x44, 0x2B, 0x2B,
0x53, 0x01, 0xD0, 0xD0, 0xD0, 0x2C, 0x2C, 0x04, 0x2C, 0x15, 0x15, 0x15, 0x48, 0x60, 0x2D, 0x00,
0x36, 0x00, 0x93, 0x70, 0x93, 0x93, 0xEC, 0xEC, 0xEC, 0x6B, 0x01, 0x9D, 0x9D, 0x20, 0x9D, 0x2F,
0x01, 0x74, 0x74, 0x74, 0x7E, 0x7E, 0x7E, 0x02, 0xA7, 0xA7, 0xA7, 0xE0, 0xE0, 0xE0, 0xE3, 0xE3,
0x00, 0xE3, 0x65, 0x65, 0x65, 0x12, 0x12, 0x12, 0x00, 0x00, 0x80, 0x62, 0x31, 0x32, 0x01, 0xAF,
0xAF, 0xAF, 0xD7, 0xD7, 0xD7, 0x03, 0x2E, 0x2E, 0x2E, 0xC9, 0x13, 0x5F, 0xF1, 0x48, 0xF0, 0x84,
0x20, 0x2E, 0x78, 0x1A, 0x1B, 0x6D, 0x11, 0x1D, 0xA9, 0x0A, 0x1E, 0x00, 0xCF, 0x07, 0x1F, 0xEA,
0x02, 0x84, 0x10, 0xEF, 0x01, 0x20, 0x20, 0xDD, 0x04, 0x1F, 0xC3, 0x08, 0x1F, 0x9A, 0x00, 0x0C,
0x1E, 0x59, 0x14, 0x1D, 0x9B, 0x01, 0x18, 0x36, 0xE0, 0xA0, 0xA1, 0xF1, 0x24, 0x1B, 0x1B, 0x7F,
0x0F, 0x1D, 0xB7, 0x01, 0x08, 0x1E, 0xAC, 0x0A, 0x1E, 0xAE, 0x0A, 0x1E, 0x00, 0x94, 0x0D, 0x1E,
0x2B, 0x1A, 0x1C, 0xE7, 0xD3, 0x02, 0xF4, 0xC0, 0x68, 0x21, 0xBA, 0x0E, 0x3E, 0x17, 0x1B, 0x89,
0x0D, 0x1E, 0x03, 0xB7, 0x09, 0x1E, 0xDB, 0x05, 0x1F, 0xF0, 0x01, 0x00, 0x20, 0xEF, 0x02, 0x20,
0xE9, 0x03, 0x20, 0xD7, 0x00, 0x05, 0x1F, 0xB4, 0x09, 0x1E, 0x85, 0x0F, 0x1E, 0x00, 0x3C, 0x18,
0x1B, 0x16, 0x99, 0xE3, 0x86, 0x31, 0x27, 0x27, 0x30, 0x27, 0x6F, 0x6F, 0x6F, 0xC0, 0xC0, 0xC0,
0xE1, 0x00, 0xE1, 0xE1, 0x3C, 0x00, 0x00, 0x00, 0xDE, 0xDE, 0xDE, 0xB8, 0x0C, 0xB8, 0xB8, 0x7B,
0x7B, 0x7B, 0x33, 0x33, 0x33, 0x00, 0x5F, 0x31, 0x5F, 0x5F, 0x5F, 0x85, 0x0B, 0x29, 0x29, 0x29,
0x11, 0x2D, 0x00, 0x26, 0xC1, 0x29, 0x01, 0x6D, 0x0B, 0xA3, 0xA3, 0xA3, 0xD8, 0x0F, 0xD8, 0xD8,
0xE2, 0xE2, 0xE2, 0x00, 0x00, 0xDF, 0xDF, 0x20, 0xDF, 0xC8, 0xC8, 0xC8, 0x8D, 0x8D, 0x8D, 0x3D,
0x00, 0x3D, 0x3D, 0x5F, 0x31, 0x38, 0x61, 0x20, 0x01, 0x63, 0x63, 0x63, 0x1C, 0x77, 0x77, 0x77,
0x25, 0x25, 0x25, 0x4A, 0x11, 0x46, 0xF0, 0xC0, 0x84, 0xF0, 0x81, 0x30, 0x1A, 0x1B, 0x18, 0x78,
0x20, 0x35, 0x18, 0x23, 0x1B, 0x4F, 0x15, 0x1D, 0x81, 0x00, 0x52, 0x14, 0x1D, 0x10, 0x41, 0x17,
0x1C, 0x28, 0x1A, 0x1B, 0x11, 0x5C, 0x21, 0x80, 0x0F, 0xF0, 0x25, 0xF0, 0x30, 0x1C, 0x1A, 0x1B,
0x17, 0xA7, 0x01, 0x11, 0x11, 0xC7, 0x23, 0x11, 0x0F, 0x1D, 0x1B, 0x1E, 0x01, 0x10, 0x4A, 0xF0,
0xDE, 0xF0, 0xE1, 0x18, 0x10, 0xAD, 0x00, 0x16, 0xEB, 0x0B, 0x1B, 0x1B, 0x40, 0x17, 0x0B, 0x1C,
0x53, 0x13, 0x1D, 0x53, 0x14, 0x1D, 0x4C, 0x00, 0x15, 0x1D, 0x3A, 0x18, 0x1B, 0x4D, 0x00, 0x0F,
0x5C, 0x01, 0xA0, 0x03, 0x20, 0xD8, 0xF0, 0xE8, 0x38, 0x15, 0x00, 0x18, 0x00, 0x42, 0x42, 0x42,
0x1F, 0x53, 0x53, 0x53, 0x4E, 0x4E, 0x4E, 0x3E, 0x3E, 0x00, 0x3E, 0x18, 0x00, 0x9A, 0x0B, 0x1E,
0x00, 0x0C, 0x00, 0x48, 0x00, 0x47, 0x01, 0x0A, 0x7E, 0x0A, 0x0A, 0x12, 0x30, 0x65, 0xC1, 0x33,
0x00, 0x18, 0x00, 0x1D, 0x01, 0x34, 0x7C, 0x34, 0x34, 0x4D, 0x4D, 0x4D, 0x54, 0x54, 0x54, 0x00,
0x48, 0x48, 0x48, 0x22, 0x22, 0x22, 0x11, 0x11, 0x00, 0x11, 0x1D, 0x01, 0xCA, 0x05, 0x29, 0x91,
0x20, 0x20, 0x20, 0xFF, 0x00, 0x8E, 0x0D, 0x0D, 0x0D, 0x76, 0x08, 0x07, 0x70, 0x42, 0xF0, 0x48,
0xF0, 0x4E, 0x50, 0xF8, 0x16, 0x87, 0x50, 0x12, 0x84, 0x20, 0x16, 0x1C, 0x36, 0xC0, 0x2F, 0xF0,
0xCA, 0x39, 0xF0, 0x00, 0x00, 0x4B, 0x50, 0x23, 0x61, 0x42, 0xF0, 0x78, 0xF0, 0x18, 0x50, 0x18,
0x7F, 0x09, 0x00, 0x1B, 0x1B, 0x12, 0x00, 0x00, 0x1C, 0x1B, 0x13, 0x11, 0x1C, 0x1B, 0x14, 0x1C,
0x1B, 0x18, 0xCF, 0x20, 0x19, 0x40, 0x05, 0x50, 0x39, 0xF0, 0x03, 0x00, 0x39, 0x30, 0x3F, 0x60,
0x3C, 0xC0, 0x50, 0xC1, 0x2D, 0xF0, 0xFF, 0x3B, 0x07, 0x0F, 0x00, 0x17, 0x17, 0x17, 0x03, 0x00,
0x08, 0x0A, 0x0B, 0x0A, 0xE3, 0x18, 0x18, 0x18, 0x15, 0x30, 0x15, 0xF0, 0x05, 0x71, 0x0F, 0xF0,
0x33, 0xF0, 0xF8, 0x81, 0xF0, 0x81, 0xF0, 0x0F, 0xF0, 0x21, 0xF0, 0x36, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0x27, 0xF0, 0xFF, 0x09, 0x80, 0x47, 0x06, 0x03, 0x30, 0x00, 0x00, 0x35, 0xC0, 0x27, 0xF0,
0x3F, 0xF0, 0x3C, 0xF0, 0xFF, 0x30, 0xF0, 0xB3, 0xF1, 0xFA, 0xF2, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x7A, 0xF1, 0x5B, 0xF8, 0x0F, 0xF0,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
0x0F, 0xF0, 0x1A, 0xF7, 0x5B, 0xF8, 0x5C, 0xFD, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x1D, 0xF7, 0xFF, 0x79, 0xFB, 0x6D,
0x9B, 0x62, 0x01, 0x00, 0x00, 0xC1, 0x02, 0x03, 0x30, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x09, 0x90, 0xFF,
0x03, 0x30, 0x00, 0x00, 0x8B, 0x3B, 0xFB, 0x3D, 0x62, 0x01, 0x81, 0x0C, 0x6A, 0x6A, 0x3F, 0x6A,
0x42, 0x0F, 0x03, 0x30, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFE, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x09, 0x90, 0x03, 0x30, 0x00, 0x00, 0x88, 0x0B,
0xFF, 0x03, 0x0C, 0x4F, 0x4F, 0x4F, 0x6D, 0x0B, 0x8F, 0x0A, 0x05, 0x0A, 0xC6, 0x0F, 0xF1, 0xA8,
0xA8, 0xA8, 0x03, 0x30, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xF8, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x09, 0x90, 0x03, 0x30, 0x00, 0x00, 0xFF, 0x9C,
0x9C, 0x9C, 0xA9, 0xA9, 0xA9, 0xCE, 0x0D, 0x09, 0x00, 0xC0, 0x62, 0x01, 0xB2, 0x08, 0x6B, 0x0A,
0xF4, 0x0B, 0x03, 0x30, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x09, 0x90, 0x03, 0x30, 0xFF, 0x00, 0x00, 0x03,
0x00, 0x0C, 0x0C, 0x0C, 0xBE, 0x08, 0xF1, 0x08, 0x86, 0xC4, 0xE3, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0C,
0xC0, 0xEA, 0xF6, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF,
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x36, 0xF0,
0xFD, 0xC2, 0xFF, 0x76, 0xC2, 0x24, 0xF0, 0x1B, 0xF0, 0x12, 0xF0, 0xAE, 0xF0, 0x24, 0xF0, 0x66,
0xF0, 0x66, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x21, 0xF0, 0x9B, 0xF1, 0x1B, 0xF0,
0x02, 0xF1, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x39, 0xF0, 0xD4, 0x67, 0x7B, 0x30, 0x15,
0x90, 0x7F, 0x62, 0x39, 0xC0, 0xFF, 0x30, 0xF0, 0xB2, 0x6B, 0x7D, 0x61, 0x90, 0xF0, 0x27, 0xF0,
0x27, 0xF0, 0xB8, 0x6E, 0x1E, 0xF0, 0xFF, 0x65, 0xF4, 0x0F, 0xF0, 0x0F, 0xF0, 0x18, 0xF0, 0x1B,
0xF0, 0x12, 0xF0, 0xA2, 0x90, 0x1E, 0xF0, 0xFF, 0x5D, 0x90, 0x02, 0xF1, 0xDB, 0xF0, 0xF7, 0x32,
0x00, 0x00, 0x21, 0x03, 0xEE, 0x32, 0x78, 0x00, 0xFF, 0x51, 0x30, 0xB7, 0x03, 0x40, 0x05, 0xF3,
0x03, 0xF2, 0x01, 0x76, 0x02, 0x39, 0x00, 0xD6, 0x32, 0xFF, 0x45, 0x90, 0x42, 0xCF, 0x18, 0x00,
0x35, 0x01, 0x9F, 0x00, 0x60, 0x90, 0x2C, 0x01, 0x27, 0x00, 0xFF, 0x90, 0x00, 0xCF, 0x30, 0x97,
0xFB, 0x82, 0x62, 0x00, 0x06, 0xE7, 0x00, 0x0F, 0xF0, 0x1E, 0xF0, 0xFF, 0x84, 0x3C, 0x4F, 0xCB,
0x65, 0xF1, 0x56, 0xF1, 0xDE, 0x36, 0xD6, 0x02, 0xC8, 0x0A, 0xA7, 0x01, 0xFF, 0x03, 0x30, 0x08,
0x61, 0x8A, 0x39, 0x83, 0x01, 0xD9, 0x02, 0x4F, 0x02, 0x14, 0xC1, 0x38, 0xC1, 0xFF, 0xD2, 0xC3,
0x72, 0x60, 0x8D, 0x60, 0x7E, 0x60, 0x2D, 0x00, 0x81, 0x00, 0x1A, 0x04, 0x4D, 0x04, 0xFF, 0x30,
0x00, 0x81, 0x06, 0xDD, 0x04, 0x74, 0x01, 0x0B, 0x04, 0xF6, 0x00, 0x2A, 0x03, 0x6F, 0x03, 0xFF,
0xCC, 0x03, 0xF0, 0x00, 0xA8, 0x03, 0x7D, 0x01, 0xC4, 0x02, 0x45, 0x60, 0x06, 0xCC, 0xD4, 0x01,
0xFF, 0xD8, 0x00, 0xC1, 0x02, 0x15, 0x03, 0x62, 0x91, 0x4D, 0x01, 0x6A, 0x02, 0x3D, 0x35, 0x0C,
0x00, 0xFF, 0x2A, 0xF3, 0x22, 0x6E, 0x76, 0x02, 0x4E, 0x03, 0x6A, 0x05, 0x66, 0x30, 0x03, 0xC3,
0x6F, 0x99, 0xFF, 0xC5, 0x01, 0x01, 0x32, 0xE2, 0xC2, 0x62, 0xF1, 0x62, 0xF1, 0x1B, 0x33, 0xD1,
0x01, 0x33, 0x00, 0xFF, 0xD9, 0x02, 0x03, 0x30, 0x03, 0x30, 0x62, 0x31, 0x7B, 0x0C, 0x2E, 0x02,
0x28, 0x02, 0x62, 0x01, 0xFF, 0x5F, 0x9A, 0x33, 0x30, 0xB1, 0x00, 0x9C, 0x00, 0x12, 0x00, 0x2A,
0x00, 0x45, 0x00, 0xED, 0x30, 0xFF, 0x08, 0x31, 0x12, 0x00, 0xBA, 0x00, 0x48, 0x00, 0x39, 0x00,
0xD8, 0x60, 0x3C, 0x00, 0x33, 0x00, 0xFF, 0x09, 0x00, 0x61, 0x02, 0x59, 0x01, 0x09, 0x00, 0x6C,
0x00, 0x70, 0x05, 0x54, 0x00, 0x7E, 0x00, 0xFF, 0xB9, 0x04, 0x1D, 0x01, 0x81, 0x00, 0x09, 0x00,
0x49, 0x02, 0x3C, 0x00, 0x20, 0x04, 0x7B, 0x30, 0xFF, 0x12, 0x00, 0x08, 0x01, 0x5A, 0x39, 0x7B,
0x30, 0xB1, 0x00, 0x0B, 0x01, 0x23, 0x01, 0xF7, 0x05, 0xFF, 0x6E, 0x04, 0x2C, 0xC4, 0xA1, 0x01,
0x37, 0x02, 0x57, 0x00, 0x7E, 0x06, 0x5D, 0x60, 0x1E, 0x00, 0xFF, 0xF9, 0x00, 0x45, 0x00, 0x4A,
0x3A, 0x6F, 0x36, 0xC7, 0x02, 0x22, 0x3B, 0x30, 0x00, 0x09, 0x33, 0xFF, 0x5D, 0x00, 0x4E, 0x00,
0xB6, 0x01, 0x36, 0x39, 0x4B, 0x00, 0xA6, 0x02, 0xB4, 0x03, 0x3C, 0x00, 0xFF, 0x38, 0x01, 0x0C,
0x00, 0x17, 0x01, 0xB4, 0x06, 0x3C, 0x00, 0xEA, 0x03, 0x1E, 0x30, 0xC0, 0xF9, 0xFF, 0x4C, 0xC8,
0x08, 0x01, 0x19, 0x02, 0x36, 0x06, 0x02, 0x01, 0x84, 0x00, 0xF9, 0x03, 0x50, 0x01, 0xFF, 0xDE,
0x00, 0x35, 0x31, 0x37, 0x05, 0x18, 0x00, 0xF6, 0x66, 0x9C, 0x60, 0x32, 0x07, 0xA6, 0x05, 0xFF,
0x1B, 0x00, 0x09, 0x03, 0x62, 0x07, 0xB7, 0x03, 0x12, 0x00, 0x55, 0x02, 0xCF, 0x00, 0x90, 0x00,
0xFF, 0x12, 0x00, 0x68, 0x01, 0x81, 0x00, 0xCD, 0x02, 0x70, 0x70, 0x70, 0x4E, 0x00, 0x8F, 0x36,
0x00, 0x0F, 0x00, 0x50, 0x50, 0x50, 0x74, 0x01, 0xAE, 0x00, 0x38, 0x01, 0xE3, 0xC8, 0x01, 0x6E,
0x04, 0xED, 0x00, 0x3F, 0x00, 0x27, 0x00, 0x5F, 0x01, 0x38, 0x01, 0xB1, 0x7F, 0xB1, 0xB1, 0xA8,
0x00, 0xEA, 0x03, 0x48, 0x00, 0x8C, 0x01, 0x12, 0x00, 0x8D, 0x30, 0xFC, 0x31, 0x02, 0x40, 0x05,
0x6E, 0x04, 0x21, 0x06, 0xF2, 0x01, 0xB9, 0x04, 0x64, 0x02, 0x43, 0x02, 0xFF, 0x75, 0x00, 0xAA,
0xAA, 0xAA, 0x5C, 0x01, 0x62, 0x61, 0xBF, 0x31, 0x03, 0x00, 0xF1, 0xA2, 0x03, 0x21, 0x00, 0x40,
0x02, 0x9F, 0x00, 0xD4, 0x01, 0xC5, 0x01, 0x5B, 0x02, 0x18, 0x00, 0xFF, 0x72, 0x06, 0xF9, 0x00,
0x22, 0x02, 0x21, 0x00, 0x40, 0x32, 0x0D, 0x02, 0x86, 0x01, 0x58, 0x02, 0xFF, 0xA7, 0x07, 0xDB,
0x00, 0x06, 0x00, 0x60, 0x00, 0xB3, 0x01, 0xF0, 0x03, 0x21, 0x00, 0x1B, 0x00, 0xFF, 0xF4, 0x02,
0xBD, 0xBD, 0xBD, 0x16, 0x02, 0xAA, 0x34, 0xC0, 0x00, 0x39, 0x00, 0xF1, 0xA4, 0x01, 0x23, 0x01,
0x97, 0x02, 0x00, 0x00, 0x0F, 0x60, 0xE1, 0x30, 0x44, 0x3A, 0xE7, 0x96, 0xFF, 0x9C, 0x00, 0xAE,
0x00, 0x3D, 0x05, 0x03, 0x03, 0x95, 0x04, 0x7C, 0x7C, 0x7C, 0x1F, 0x92, 0x01, 0x8D, 0x00, 0xCA,
0x02, 0x12, 0x00, 0x5D, 0x00, 0x62, 0x31, 0x91, 0x95, 0xA3, 0x02, 0xFF, 0xCE, 0x01, 0x3C, 0x00,
0xCF, 0x00, 0x21, 0x03, 0xAF, 0xAF, 0xAF, 0x68, 0x01, 0x8F, 0xA5, 0x00, 0xF8, 0x01, 0x6D, 0x6D,
0x6D, 0x3F, 0x00, 0x37, 0x02, 0x7B, 0x00, 0xE3, 0x51, 0x00, 0x51, 0x03, 0x1E, 0x06, 0xA4, 0x01,
0xB7, 0x00, 0x1D, 0x01, 0xBE, 0x02, 0x66, 0x7F, 0x66, 0x66, 0x66, 0x00, 0xEF, 0x01, 0x5D, 0x00,
0xD2, 0x00, 0xC7, 0x02, 0x09, 0x00, 0xFC, 0x62, 0x01, 0xC3, 0x00, 0xE2, 0x02, 0x5B, 0x05, 0x05,
0x01, 0x1B, 0x00, 0xBB, 0x02, 0x0F, 0x00, 0xFF, 0x5A, 0x00, 0x08, 0x01, 0x90, 0x00, 0xD5, 0x00,
0xE9, 0x01, 0x52, 0x02, 0x30, 0x03, 0x1B, 0x00, 0xFF, 0x7C, 0x02, 0x6B, 0x01, 0x30, 0x03, 0x00,
0x03, 0xBA, 0xBA, 0xBA, 0x5D, 0x00, 0x8F, 0x62, 0x91, 0x9F, 0x03, 0xB2, 0x02, 0x0F, 0x00, 0x5A,
0x00, 0x30, 0x00, 0xA2, 0x00, 0x7B, 0x30, 0xFF, 0x8A, 0x8A, 0x8A, 0xEA, 0x00, 0x51, 0x03, 0xD7,
0x01, 0x68, 0x01, 0x0F, 0x00, 0xF8, 0x73, 0x02, 0x38, 0x01, 0x9F, 0x00, 0x8F, 0x01, 0x6F, 0x03,
0x7E, 0x00, 0x72, 0x00, 0x5D, 0x03, 0xFF, 0x00, 0x00, 0xFC, 0x03, 0x7E, 0x03, 0x17, 0x04, 0xDE,
0x00, 0xC9, 0x00, 0x26, 0x01, 0x55, 0x7F, 0x55, 0x55, 0x15, 0x00, 0x8E, 0x05, 0x06, 0x00, 0xE9,
0x01, 0x3C, 0x00, 0xDB, 0x00, 0xFC, 0xEA, 0x03, 0xB4, 0x00, 0x0C, 0x00, 0x3D, 0x38, 0x90, 0x00,
0x5C, 0x01, 0xC7, 0x38, 0x91, 0x95, 0xFF, 0x3A, 0x02, 0xC3, 0x03, 0x62, 0x01, 0xBE, 0x02, 0xB4,
0xB4, 0xB4, 0x7B, 0x00, 0x8F, 0x0E, 0x01, 0xCA, 0x02, 0xFE, 0x04, 0x12, 0x00, 0xF0, 0x00, 0x62,
0x01, 0x62, 0xF1, 0xBA, 0x00, 0xFF, 0x8F, 0x01, 0x09, 0x09, 0x09, 0x5D, 0x00, 0x27, 0x00, 0x02,
0x04, 0x77, 0x01, 0xF1, 0xA0, 0x35, 0x69, 0x00, 0x60, 0x00, 0x83, 0x01, 0x38, 0x01, 0x0F, 0x00,
0x52, 0x52, 0x3F, 0x52, 0x75, 0x03, 0x69, 0x00, 0xBC, 0x01, 0x28, 0x05, 0x6A, 0x02, 0x12, 0x00,
0xE0, 0x01, 0xFE, 0xC0, 0x00, 0x66, 0x00, 0x30, 0x00, 0x27, 0x00, 0xDE, 0x00, 0xBA, 0x00, 0x8F,
0x01, 0x7D, 0x7F, 0x7D, 0x7D, 0x4D, 0x01, 0xD7, 0x01, 0xC7, 0x32, 0x62, 0x01, 0x41, 0x04, 0x99,
0x00, 0xFC, 0xE4, 0x03, 0x72, 0x00, 0x52, 0x02, 0x9E, 0x01, 0x94, 0x02, 0x9C, 0x00, 0x33, 0x00,
0x03, 0x7F, 0x03, 0x03, 0xFF, 0x03, 0x63, 0x00, 0x2A, 0x00, 0x62, 0xC1, 0xB1, 0x03, 0xC3, 0x30,
0xFC, 0x2C, 0x04, 0x12, 0x00, 0x62, 0x01, 0x63, 0x00, 0xA7, 0xA7, 0xA7, 0xB6, 0x04, 0x8F, 0x77,
0x01, 0xAD, 0x04, 0x9A, 0x9A, 0x9A, 0xFD, 0x05, 0x62, 0x01, 0xAD, 0x63, 0xAD, 0xAD, 0xD1, 0x01,
0xA8, 0x00, 0xA4, 0x04, 0x0D, 0x35, 0x02, 0x01, 0x53, 0x7C, 0x53, 0x53, 0xBD, 0x03, 0x60, 0x00,
0xF3, 0x00, 0xC7, 0x32, 0xDE, 0x00, 0x47, 0x01, 0xFC, 0x62, 0x31, 0xA6, 0xA6, 0xA6, 0xD3, 0x35,
0x04, 0x02, 0xA4, 0xA4, 0x31, 0xA4, 0xE0, 0x01, 0x45, 0x00, 0x3F, 0x36, 0x54, 0x00, 0xC6, 0x00,
0x51, 0x00, 0xA6, 0x02, 0xFE, 0xA8, 0x36, 0xC7, 0x62, 0xCF, 0x00, 0x62, 0x31, 0x72, 0x03, 0x0C,
0x00, 0xB1, 0x00, 0x8C, 0x01, 0xFF, 0xFF, 0x00, 0x19, 0x02, 0x53, 0x01, 0x5D, 0x00, 0x62, 0xF1,
0x2A, 0x03, 0x4D, 0x01, 0xED, 0x00, 0xFF, 0x4B, 0x4B, 0x4B, 0xCC, 0x00, 0x32, 0x04, 0x84, 0x00,
0xC7, 0x02, 0xCB, 0x01, 0xF8, 0x3C, 0x00, 0xC1, 0x02, 0x12, 0x00, 0x15, 0x00, 0x27, 0x00, 0x45,
0x45, 0x45, 0x1F, 0x04, 0x02, 0xE0, 0x04, 0x62, 0x01, 0x1E, 0x00, 0x48, 0x00, 0x1E, 0x00, 0xCF,
0x03, 0xED, 0x00, 0xFF, 0xCB, 0x01, 0x3E, 0x3E, 0x3E, 0x02, 0x01, 0xC6, 0x00, 0x31, 0x02, 0x09,
0x00, 0xF1, 0x62, 0x61, 0x84, 0x00, 0x81, 0x81, 0x81, 0xA1, 0x01, 0x54, 0x54, 0x23, 0x54, 0x3C,
0x00, 0xCB, 0x01, 0x00, 0x00, 0xD9, 0x02, 0x08, 0x01, 0x7A, 0x04, 0x5D, 0x00, 0xFE, 0x25, 0x02,
0xC8, 0x01, 0x20, 0x01, 0x2D, 0x03, 0x78, 0x00, 0x56, 0x01, 0x93, 0x30, 0x87, 0x00, 0xFF, 0x5E,
0x02, 0x62, 0x01, 0x7B, 0x00, 0xAE, 0x00, 0x5D, 0x5D, 0x5D, 0xFE, 0x01, 0x8F, 0xCF, 0x00, 0x1A,
0x01, 0x38, 0x01, 0x00, 0x00, 0x45, 0x30, 0xDB, 0x03, 0xF9, 0x00, 0x03, 0x03, 0xFF, 0xE2, 0x02,
0xD1, 0x01, 0x20, 0x01, 0x39, 0x30, 0x7D, 0x01, 0x84, 0x84, 0x84, 0x1F, 0x40, 0x02, 0x6F, 0x6F,
0x6F, 0x29, 0x01, 0x30, 0x00, 0x0D, 0x02, 0xE3, 0x01, 0xF1, 0x09, 0x00, 0x68, 0x01, 0x72, 0x00,
0x4E, 0x00, 0x62, 0x01, 0xB1, 0x03, 0x72, 0x72, 0x3F, 0x72, 0xE1, 0x03, 0xA6, 0x02, 0x2A, 0x03,
0xA5, 0x00, 0x5C, 0x31, 0x02, 0x01, 0x00, 0x00, 0xFE, 0x5B, 0x5B, 0x5B, 0x2A, 0x00, 0x51, 0x00,
0x62, 0x61, 0x81, 0x00, 0x62, 0x31, 0xF8, 0xD7, 0x01, 0xA2, 0xA2, 0xA2, 0xD7, 0x31, 0x21, 0x00,
0x48, 0x00, 0xE4, 0x00, 0xF1, 0xF7, 0x02, 0x5D, 0x00, 0x41, 0x41, 0x41, 0x72, 0x00, 0x09, 0x66,
0xA2, 0x00, 0xE3, 0x89, 0x89, 0x89, 0x44, 0x44, 0x44, 0x87, 0x00, 0x3F, 0x03, 0xC0, 0x49, 0x02,
0x62, 0x01, 0x12, 0x00, 0xB7, 0x03, 0x46, 0x02, 0x1E, 0x1E, 0x1E, 0x1F, 0x5F, 0x5F, 0x5F, 0x94,
0x94, 0x94, 0x29, 0x29, 0x00, 0x29, 0x48, 0x00, 0x27, 0x00, 0x92, 0x92, 0x92, 0x48, 0x00, 0x72,
0x00, 0xC6, 0x97, 0x97, 0x97, 0xE7, 0x30, 0x66, 0x03, 0x20, 0x01, 0x86, 0x01, 0x24, 0x00, 0xF8,
0x30, 0x00, 0x36, 0x36, 0x36, 0xC3, 0x00, 0x09, 0x00, 0x80, 0x80, 0x31, 0x80, 0xB5, 0x02, 0xE1,
0x00, 0x0A, 0x02, 0x82, 0x82, 0x82, 0xED, 0x00, 0x8E, 0x4E, 0x03, 0x45, 0x00, 0x3F, 0x3F, 0x3F,
0x35, 0x01, 0x00, 0x00, 0x45, 0x00, 0xE3, 0x87, 0x00, 0xCF, 0x00, 0x4D, 0x01, 0x96, 0x00, 0x94,
0x02, 0xA1, 0xA1, 0xA1, 0x1F, 0x57, 0x00, 0x63, 0x00, 0x62, 0x61, 0x61, 0x02, 0x42, 0x00, 0x93,
0x00, 0x9D, 0x02, 0xE7, 0x00, 0xFF, 0x9C, 0x9C, 0x9C, 0xB5, 0x02, 0x49, 0x49, 0x49, 0x39, 0x00,
0x88, 0x75, 0x00, 0x57, 0x00, 0x56, 0x01, 0x73, 0x02, 0x45, 0x00, 0x03, 0x03, 0x62, 0x01, 0x84,
0x00, 0xFF, 0x6E, 0x01, 0xD0, 0x02, 0x98, 0x01, 0x6C, 0x6C, 0x6C, 0x96, 0x96, 0x07, 0x96, 0x21,
0x00, 0x9F, 0x00, 0xCE, 0x01, 0x97, 0x02, 0x0A, 0x0A, 0x0A, 0x1E, 0x43, 0x43, 0x43, 0x9C, 0x00,
0xCA, 0x02, 0x21, 0x00, 0x79, 0x02, 0xAA, 0x01, 0xF8, 0x3C, 0x00, 0x1F, 0x02, 0x15, 0x03, 0x47,
0x01, 0x65, 0x61, 0x69, 0x33, 0xAE, 0x00, 0x4E, 0x03, 0xFF, 0x73, 0x32, 0x62, 0x61, 0xDA, 0x01,
0x3C, 0x00, 0x2A, 0x00, 0x12, 0x00, 0xA5, 0xA5, 0x3F, 0xA5, 0x27, 0x00, 0x1B, 0x00, 0x7E, 0x00,
0x8A, 0x00, 0x2C, 0x2C, 0x2C, 0x1E, 0x62, 0x01, 0x88, 0x88, 0x88, 0x62, 0x01, 0xB1, 0x00, 0x20,
0x31, 0x6E, 0x01, 0xF1, 0x2B, 0x02, 0x3F, 0x00, 0xD2, 0x00, 0x72, 0x00, 0x47, 0x47, 0x47, 0x2A,
0x00, 0x8F, 0x28, 0x02, 0x48, 0x00, 0x63, 0x63, 0x63, 0x7F, 0x7F, 0x7F, 0x03, 0x7B, 0x30, 0x8E,
0x8E, 0x8E, 0x78, 0x00, 0x71, 0x71, 0x71, 0x11, 0xA5, 0x00, 0xBC, 0x01, 0x0B, 0x0B, 0x0B, 0xFF,
0x00, 0x93, 0x93, 0x23, 0x93, 0x8B, 0x8B, 0x8B, 0x69, 0x69, 0x69, 0xC3, 0x03, 0x80, 0x06, 0x00,
0x3B, 0x01, 0xB9, 0x01, 0x8D, 0x8D, 0x8D, 0x51, 0x00, 0xA0, 0x02, 0xC7, 0x36, 0x00, 0x1B, 0x00,
0x05, 0x01, 0xD1, 0x01, 0x58, 0x58, 0x58, 0x87, 0x0F, 0x87, 0x87, 0x0C, 0x03, 0x8D, 0x00, 0x68,
0x01, 0x8D, 0x00, 0x45, 0x30, 0x54, 0x00, 0xFC, 0x12, 0x00, 0x4D, 0x4D, 0x4D, 0x27, 0x00, 0x3F,
0x00, 0x57, 0x00, 0xC1, 0x71, 0xC1, 0xC1, 0xB6, 0x01, 0x30, 0x00, 0x00, 0x00, 0x90, 0x30, 0x53,
0x01, 0x90, 0x7C, 0x90, 0x90, 0x93, 0x00, 0xB6, 0x01, 0x56, 0x56, 0x56, 0xF2, 0x01, 0x8C, 0x60,
0x00, 0xB4, 0x00, 0x4E, 0x00, 0x98, 0x98, 0x98, 0x1D, 0x01, 0x85, 0x47, 0x85, 0x85, 0xCC, 0x00,
0x0C, 0x0C, 0x0C, 0x75, 0x75, 0x04, 0x75, 0x91, 0x91, 0x91, 0x1B, 0x00, 0x57, 0x57, 0x57, 0x10,
0x9F, 0x9F, 0x9F, 0x34, 0x34, 0x34, 0x46, 0x46, 0x00, 0x46, 0x9B, 0x9B, 0x9B, 0xA8, 0x00, 0xBA,
0x00, 0xB8, 0xB8, 0x30, 0xB8, 0x62, 0x62, 0x62, 0x07, 0x07, 0x07, 0x29, 0x01, 0x80, 0x99, 0x99,
0x99, 0x86, 0x86, 0x86, 0x36, 0x00, 0x78, 0x00, 0xC0, 0x79, 0x79, 0x79, 0x9D, 0x9D, 0x9D, 0x68,
0x68, 0x00, 0x68, 0x83, 0x83, 0x83, 0x5C, 0x5C, 0x5C, 0x13, 0x32, 0x80, 0x0C, 0x90, 0x35, 0xF4,
0x30, 0x30, 0x30, 0x8F, 0x8F, 0x8F, 0x03, 0x14, 0x01, 0x36, 0x00, 0xAC, 0xAC, 0xAC, 0x95, 0x95,
0x95, 0x03, 0x6B, 0x6B, 0x6B, 0xA0, 0xA0, 0xA0, 0x5C, 0x01, 0x46, 0x02, 0xC0, 0x15, 0x00, 0x8C,
0x8C, 0x8C, 0xE1, 0x00, 0x71, 0x01, 0x3C, 0x63, 0x22, 0x71, 0x22, 0x22, 0x48, 0x00, 0x26, 0x26,
0x26, 0x60, 0x00, 0xF6, 0x03, 0xC4, 0x54, 0x00, 0x35, 0x01, 0x18, 0x00, 0x60, 0x00, 0x35, 0x35,
0x35, 0x41, 0x31, 0x8F, 0x2D, 0x2D, 0x2D, 0x6A, 0x6A, 0x6A, 0x7E, 0x7E, 0x00, 0x7E, 0x12, 0x00,
0xCC, 0x33, 0x8D, 0x00, 0x32, 0x32, 0x32, 0x02, 0x01, 0x8E, 0x6E, 0x6E, 0x6E, 0x4F, 0x4F, 0x4F,
0x12, 0x00, 0x36, 0x00, 0xC0, 0x02, 0x31, 0x51, 0x60, 0x37, 0x37, 0x37, 0x2F, 0x01, 0x45, 0x30,
0x38, 0x63, 0x38, 0x38, 0x6F, 0x00, 0x24, 0x00, 0x24, 0x24, 0x24, 0x5A, 0x0C, 0x5A, 0x5A, 0x78,
0x78, 0x78, 0x67, 0x67, 0x67, 0x00, 0x2E, 0x2E, 0x2E, 0x08, 0x01, 0x3E, 0x01, 0x06, 0x00, 0x7A,
0x7A, 0x38, 0x7A, 0x5E, 0x5E, 0x5E, 0x4C, 0x4C, 0x4C, 0x78, 0x03, 0x80, 0x1E, 0x00, 0x78, 0x60,
0x96, 0x00, 0xFB, 0x01, 0x57, 0x00, 0x45, 0x00, 0x15, 0x00, 0x40, 0x7F, 0x40, 0x40, 0x5D, 0x00,
0xB4, 0x00, 0x28, 0x28, 0x28, 0x4B, 0x03, 0x8C, 0x36, 0x00, 0x84, 0x00, 0x2B, 0x2B, 0x2B, 0xC3,
0x00, 0x33, 0x33, 0x23, 0x33, 0x3C, 0x3C, 0x3C, 0x1B, 0x00, 0x99, 0x00, 0x42, 0x42, 0x30, 0x42,
0x2F, 0x2F, 0x2F, 0x30, 0x00, 0x4E, 0x4E, 0x4E, 0x10, 0x7B, 0x7B, 0x7B, 0x1B, 0x00, 0x48, 0x48,
0x48, 0x1E, 0x00, 0x88, 0x1E, 0x33, 0x4A, 0x4A, 0x4A, 0x77, 0x77, 0x77, 0x3F, 0x00, 0x81, 0xEA,
0x00, 0x4E, 0x00, 0x59, 0x59, 0x59, 0x76, 0x76, 0x76, 0x03, 0x65, 0x65, 0x65, 0x31, 0x31, 0x31,
0x3C, 0x00, 0x0C, 0xC0, 0xC0, 0x53, 0xF1, 0x21, 0x21, 0x21, 0x1B, 0x00, 0x1F, 0x1F, 0x1F, 0x11,
0x3D, 0x3D, 0x3D, 0xA3, 0xA3, 0xA3, 0x73, 0x73, 0x00, 0x73, 0x74, 0x74, 0x74, 0x61, 0x61, 0x61,
0x20, 0x00, 0x20, 0x20, 0x21, 0x00, 0x23, 0x23, 0x23, 0x39, 0x39, 0x04, 0x39, 0x25, 0x25, 0x25,
0x09, 0x00, 0x89, 0x91, 0x09, 0x00, 0x5A, 0x00, 0xF0, 0x09, 0x00, 0x21, 0x00, 0x09, 0x00, 0x27,
0x30, 0x60, 0x00, 0x27, 0x00, 0x00, 0x00, 0x12, 0x30, 0xFF, 0x99, 0x30, 0x23, 0x91, 0x3C, 0x00,
0xCC, 0x33, 0x0E, 0x0E, 0x0E, 0x12, 0x00, 0x8F, 0x02, 0xC1, 0x15, 0x30, 0x7B, 0x00, 0x45, 0x30,
0x09, 0x00, 0x27, 0x00, 0x8D, 0xC0, 0x39, 0x00, 0xFF, 0x4E, 0x30, 0x33, 0x00, 0x14, 0x31, 0x57,
0x00, 0x30, 0x00, 0x78, 0xC0, 0xAE, 0x60, 0x2A, 0x00, 0xFF, 0x0F, 0x0F, 0x0F, 0x5A, 0x00, 0x39,
0x30, 0x03, 0x00, 0x06, 0x00, 0x13, 0x78, 0x13, 0x13, 0x1E, 0x00, 0x3C, 0x30, 0x06, 0x00, 0x1B,
0x00, 0x7B, 0x00, 0x5D, 0x30, 0xFC, 0xB4, 0x00, 0x09, 0x00, 0x18, 0x30, 0x1E, 0x03, 0x06, 0x00,
0x09, 0x30, 0xB3, 0x01, 0x03, 0x00, 0xFF, 0x09, 0x00, 0x12, 0x00, 0x48, 0x00, 0x12, 0x12, 0x12,
0x1D, 0x1D, 0x07, 0x1D, 0x00, 0x00, 0x39, 0x00, 0x3C, 0x00, 0x0F, 0xF0, 0x36, 0xF0, 0x10, 0x10,
0x3E, 0x10, 0x17, 0x17, 0x17, 0x3A, 0x3A, 0x3A, 0xAE, 0x00, 0xAE, 0xAE, 0x3B, 0x3B, 0x3B, 0x0F,
0x00, 0x14, 0x14, 0x20, 0x14, 0x16, 0x16, 0x16, 0x09, 0x00, 0x39, 0x00, 0x11, 0x11, 0x30, 0x11,
0x36, 0x00, 0xB2, 0xF2, 0x3C, 0xF0, 0x90, 0xF0, 0x90, 0xF0, 0x36, 0x30, 0x7B, 0x90, 0xFE, 0x0F,
0xF0, 0x2A, 0xF0, 0x0F, 0xF0, 0x57, 0xF0, 0x0F, 0xF0, 0x18, 0xF0, 0x27, 0x00, 0x21, 0x00, 0xFF,
0x45, 0xF0, 0x12, 0xF0, 0x60, 0x60, 0x0C, 0xC0, 0x30, 0x60, 0x18, 0x18, 0x18, 0x1F, 0x2A, 0x00,
0x03, 0x30, 0x0F, 0xF0, 0x24, 0xF0, 0x00, 0x00, 0x1A, 0x1A, 0x1A, 0x1F, 0x27, 0x27, 0x27, 0x60,
0x60, 0x60, 0x2A, 0x2A, 0x00, 0x2A, 0x15, 0x15, 0x15, 0x5C, 0x01, 0x00, 0x00, 0x0F, 0xF0, 0x0F,
0xF0, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0xFF, 0x18, 0xF0, 0x0D, 0x0D, 0x0D, 0x19, 0x19, 0x19, 0x1C, 0x01, 0x1C, 0x1C,
0x06, 0x60, 0x03, 0x30, 0x00, 0x00, 0x1B, 0x1B, 0x1B, 0x1C, 0xFF, 0xFF, 0xA8, 0x1D, 0x00, 0x00,
0x0E, 0x00, 0x00, 0x00, 0xD5, 0x31, 0x00, 0x00
};
#endif //MENU_LOGO_ENABLE
// 68 x 192 @8bpp Grayscale RAW.
#define X_BOOTLOGO 68
#define Y_BOOTLOGO 192
#define SZ_BOOTLOGO 13056
#define SZ_BOOTLOGO_BLZ 6704
static u8 BOOTLOGO_BLZ[SZ_BOOTLOGO_BLZ] = {
0x0F, 0xF0, 0x80, 0x1B, 0x1B, 0x77, 0xF0, 0x6A, 0x08, 0x41, 0x80, 0x0F, 0x4D, 0x21, 0x40, 0x29,
0xF0, 0xFC, 0x34, 0xED, 0x34, 0x10, 0x23, 0x26, 0x27, 0x23, 0x76, 0x30, 0x0F, 0xF0, 0xC3, 0xC9,
0xF0, 0x3F, 0x7F, 0xC6, 0x53, 0x80, 0x2E, 0x33, 0xDB, 0x2D, 0xBA, 0x20, 0x8F, 0x1C, 0xE7, 0x76,
0x23, 0xF8, 0x0E, 0x40, 0xF0, 0x54, 0x9C, 0x1E, 0x21, 0x3A, 0x1F, 0xBD, 0x71, 0x20, 0x2F, 0x3D,
0xDB, 0x35, 0xFE, 0x00, 0x82, 0x19, 0xB1, 0x9E, 0x83, 0x5D, 0x22, 0x85, 0x1C, 0x93, 0xB1, 0x44,
0x3F, 0xD2, 0x29, 0x63, 0x26, 0x39, 0x88, 0x33, 0x45, 0xDA, 0x38, 0x08, 0x9E, 0x50, 0x32, 0x56,
0x78, 0x75, 0x27, 0x1D, 0x1D, 0x99, 0xE6, 0xE8, 0xC3, 0x28, 0x33, 0xD0, 0x2B, 0x21, 0xC9, 0xB0,
0x49, 0xB9, 0x1C, 0x60, 0x30, 0x4F, 0xA1, 0x6D, 0x3A, 0x36, 0x37, 0x36, 0x00, 0x34, 0x2B, 0x79,
0x3C, 0x51, 0xF1, 0x2E, 0x3C, 0xD2, 0x32, 0x0C, 0x26, 0x19, 0xC6, 0x9F, 0x70, 0x95, 0x21, 0x8D,
0xBB, 0xBC, 0xBA, 0x0E, 0xBB, 0xBB, 0xBA, 0xBC, 0xBB, 0xF4, 0x10, 0x4E, 0xF1, 0xC9, 0x10, 0xE0,
0xD2, 0x36, 0xC9, 0x90, 0x11, 0x1E, 0x19, 0xA0, 0x1C, 0x27, 0x3F, 0x1C, 0x52, 0x54, 0x51, 0x51,
0x50, 0x51, 0x4D, 0x3A, 0x00, 0x24, 0xE0, 0x87, 0x38, 0x60, 0xC9, 0x10, 0x0D, 0xB1, 0x34, 0x59,
0xDA, 0xB1, 0x13, 0xDE, 0x93, 0x25, 0x28, 0x27, 0x88, 0x2D, 0xEB, 0x9A, 0x6A, 0x46, 0x1F, 0xC9,
0x70, 0xB9, 0x81, 0xF4, 0x71, 0x4C, 0x29, 0x02, 0x30, 0x2A, 0x1F, 0x73, 0x02, 0x7C, 0x22, 0xC7,
0x90, 0xD4, 0xB0, 0x24, 0xD4, 0x37, 0x25, 0x85, 0xB0, 0x27, 0x6B, 0xA4, 0xA3, 0x08, 0x0C, 0x47,
0x91, 0xAC, 0xBB, 0x2C, 0x27, 0x72, 0x01, 0x54, 0x22, 0x6F, 0x60, 0xF7, 0xBC, 0x6C, 0x14, 0x25,
0x7D, 0x88, 0x48, 0x5C, 0xDA, 0x3B, 0x7D, 0xA8, 0x84, 0x08, 0x48, 0xAB, 0x8A, 0x6A, 0x0C, 0xA7,
0x32, 0x2B, 0x56, 0xA8, 0x2B, 0x02, 0x20, 0x2C, 0xF2, 0xC0, 0x6C, 0x14, 0x34, 0x14, 0x05, 0x99,
0x09, 0xB5, 0x30, 0x7C, 0x8C, 0x45, 0x0F, 0x50, 0xA5, 0x30, 0x27, 0x42, 0x91, 0xAD, 0x1B, 0x1E,
0xFE, 0xC0, 0xB0, 0x04, 0x6C, 0x04, 0x2C, 0x79, 0x22, 0x95, 0x21, 0x0A, 0x65, 0x1A, 0xE9, 0x22,
0xB7, 0x8A, 0x69, 0x33, 0x45, 0xA4, 0x2E, 0x24, 0xF5, 0x27, 0x80, 0x1C, 0x1F, 0x23, 0x24, 0x25,
0x26, 0x51, 0x11, 0x26, 0x40, 0x25, 0x4C, 0x01, 0x99, 0x07, 0x25, 0x25, 0x2C, 0x3A, 0x4A, 0x06,
0xD3, 0xC4, 0x33, 0x60, 0x45, 0x48, 0x79, 0x2C, 0xA4, 0x23, 0xED, 0x5F, 0x75, 0x76, 0x89, 0x37,
0x46, 0xA4, 0x32, 0x2B, 0x47, 0xAA, 0x00, 0x42, 0x1E, 0x1D, 0x20, 0x29, 0x2F, 0x0A, 0x10, 0x38,
0x40, 0x01, 0x10, 0x37, 0x01, 0x00, 0x36, 0x37, 0x37, 0x37, 0x3B, 0x05, 0x47, 0x50, 0xD2, 0xFC,
0x1F, 0xB5, 0xB3, 0x1C, 0xFA, 0xB3, 0xA5, 0x58, 0x8C, 0x64, 0xA7, 0x4C, 0x5B, 0x9F, 0x89, 0x2B,
0x00, 0x1D, 0x1D, 0x24, 0x2F, 0xD1, 0x01, 0x10, 0xD2, 0x01, 0x10, 0xA0, 0xD2, 0xD3, 0xD3, 0xD3,
0xD4, 0xD4, 0xD4, 0xD2, 0x00, 0xD2, 0xD4, 0xD4, 0xED, 0x34, 0xE0, 0x72, 0x20, 0xF5, 0x27, 0xA0,
0x6E, 0x5B, 0x71, 0x50, 0x56, 0x90, 0xB6, 0xBA, 0xBA, 0xB0, 0x03, 0x86, 0x36, 0x25, 0x0B, 0x21,
0x2B, 0x38, 0x3F, 0x02, 0x10, 0x84, 0x42, 0x02, 0x10, 0x40, 0x00, 0x00, 0x41, 0x41, 0x41, 0x43,
0x0A, 0x46, 0x45, 0x3B, 0x2D, 0x20, 0xBD, 0xCC, 0x68, 0xD8, 0x30, 0x60, 0x41, 0x4F, 0x54, 0x4F,
0x43, 0x33, 0x24, 0x16, 0x04, 0x80, 0x1E, 0x24, 0x2C, 0x2F, 0x30, 0x31, 0x0A, 0x00, 0x32, 0x40,
0x32, 0x31, 0x31, 0x30, 0x31, 0x32, 0x31, 0x30, 0x00, 0x30, 0x31, 0x31, 0x32, 0x2F, 0x2B, 0xD4,
0x75, 0xBD, 0x5C, 0xC0, 0x61, 0xA9, 0x7F, 0x00, 0x9C, 0x05, 0x29, 0x24, 0x1F, 0x1D, 0xC1, 0x29,
0x87, 0x20, 0x22, 0x21, 0x22, 0x26, 0x15, 0x0B, 0x22, 0x21, 0x20, 0x20, 0x21, 0x20, 0x21, 0x20,
0x4F, 0x1E, 0x1F, 0x1E, 0x20, 0x1E, 0x1D, 0x85, 0x90, 0x39, 0xB8, 0x1D, 0x23, 0x2B, 0x30, 0x0C,
0x2E, 0x2F, 0x2F, 0x2F, 0x2F, 0x30, 0x2D, 0x2F, 0x00, 0x2C, 0x35, 0x26, 0x1C, 0x1D, 0x1E, 0x24,
0x29, 0x2C, 0x02, 0x31, 0x31, 0x2D, 0x28, 0x25, 0x1E, 0x1E, 0x4D, 0x53, 0x80, 0x09, 0xF5, 0x41,
0xA0, 0xA4, 0xA6, 0xA5, 0xA6, 0xA7, 0x39, 0x18, 0x83, 0xA7, 0xA5, 0xA2, 0x25, 0xAF, 0x28, 0x29,
0x32, 0x3A, 0x10, 0x7D, 0xA0, 0xAB, 0xA0, 0x6E, 0x35, 0x2A, 0x21, 0x00, 0x9D, 0xFB, 0x1B, 0xCD,
0x5D, 0x1C, 0x96, 0x6F, 0x72, 0x76, 0x7E, 0x0D, 0xA5, 0x8D, 0x74, 0x72, 0x73, 0x7A, 0x9D, 0x8C,
0x00, 0x2B, 0x1F, 0x10, 0x2B, 0x3A, 0x8B, 0xDD, 0xC1, 0xA3, 0x02, 0x82, 0xAD, 0xC2, 0xE4, 0x6C,
0x2D, 0x22, 0x1D, 0x00, 0xC4, 0x32, 0x35, 0xFC, 0x9D, 0x8A, 0x1D, 0x24, 0x2E, 0x36, 0x42, 0x07,
0x74, 0x8F, 0x41, 0x35, 0x33, 0x35, 0x40, 0x51, 0x00, 0x9E, 0x30, 0x1D, 0x1B, 0x1F, 0x29, 0x3A,
0x98, 0x00, 0xDC, 0x59, 0x43, 0x3F, 0x3F, 0x43, 0x49, 0x77, 0x00, 0xD2, 0x6C, 0x06, 0x29, 0x5D,
0xF6, 0x2D, 0x13, 0x25, 0x88, 0x1D, 0x1E, 0x3C, 0x23, 0x37, 0x8A, 0x68, 0x2B, 0x12, 0x27, 0x3F,
0x8A, 0x10, 0x61, 0x1F, 0x1C, 0x24, 0x34, 0x64, 0xDC, 0x58, 0x00, 0x3B, 0x2F, 0x2C, 0x2A, 0x30,
0x38, 0x45, 0x69, 0x00, 0xDB, 0x33, 0x24, 0xBC, 0x79, 0xBD, 0x9C, 0xE1, 0xDA, 0x21, 0x36, 0x38,
0x84, 0x62, 0x09, 0x19, 0x1C, 0x28, 0x43, 0x98, 0x59, 0x02, 0x20, 0x1E, 0x2A, 0x3B, 0xB7, 0x8C,
0x3A, 0x29, 0x00, 0x21, 0x1E, 0x1F, 0x21, 0x28, 0x37, 0x45, 0xB6, 0x00, 0x88, 0x2C, 0x20, 0xC2,
0xF5, 0x21, 0x7D, 0x28, 0x31, 0x50, 0xA5, 0x42, 0xE8, 0x54, 0xB0, 0x7B, 0x37, 0x33, 0x37, 0x4D,
0x8D, 0x00, 0xA4, 0x30, 0x1E, 0x1E, 0x2F, 0x3F, 0xD2, 0x3F, 0x00, 0x2E, 0x1F, 0x86, 0x36, 0x3B,
0x7F, 0xAA, 0x30, 0x8E, 0x56, 0x84, 0x58, 0x76, 0xD9, 0x41, 0x05, 0xC6, 0x38, 0x61, 0xA1, 0xBB,
0xAB, 0x07, 0xAB, 0xB5, 0x92, 0x47, 0x24, 0x41, 0x20, 0x3A, 0x27, 0x20, 0x1D, 0x2A, 0x30, 0x36,
0x44, 0xD2, 0x33, 0x3A, 0x95, 0x1A, 0x42, 0xA1, 0x76, 0x85, 0xC0, 0xFD, 0x0B, 0x34, 0x44, 0x4A,
0x48, 0x47, 0x07, 0x45, 0x38, 0x15, 0x03, 0x20, 0x30, 0x41, 0x10, 0xCD, 0x43, 0x32, 0x64, 0x42,
0xD2, 0xBD, 0x00, 0x84, 0x60, 0x7D, 0x30, 0x35, 0x1C, 0xAD, 0x3B, 0x7B, 0xC8, 0xFC, 0x25, 0x25,
0x25, 0x25, 0xA2, 0x16, 0xC9, 0x20, 0x37, 0x8D, 0x3B, 0xB0, 0xBD, 0x00, 0x41, 0x20, 0x1C, 0xE5,
0xF6, 0x3D, 0x14, 0x61, 0xD2, 0x3A, 0x08, 0x29, 0x7B, 0x28, 0x60, 0x02, 0x1E, 0xE4, 0x0B, 0x40,
0xD2, 0x7A, 0x5F, 0x1F, 0x4A, 0x32, 0x41, 0xD2, 0x38, 0x25, 0x46, 0x50, 0xD9, 0x81, 0x2D, 0x23,
0xE0, 0x0C, 0xD8, 0x44, 0x80, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x01, 0x93, 0x24, 0x71, 0x08, 0x09,
0x70, 0x20, 0x35, 0x00, 0x36, 0x7E, 0x85, 0xAC, 0x1C, 0x3D, 0xA4, 0x95, 0x51, 0x87, 0x4D, 0x4A,
0xAB, 0x96, 0x95, 0x0E, 0xB2, 0x92, 0x90, 0xAB, 0x7A, 0x28, 0x1B, 0x1F, 0x00, 0x31, 0x41, 0xD3,
0x39, 0x2A, 0xA3, 0x01, 0x06, 0x00, 0x24, 0x60, 0x36, 0x45, 0xD4, 0x3B, 0x29, 0x1F, 0x86, 0x01,
0x1E, 0x40, 0x1F, 0x1D, 0x1C, 0x8D, 0xD9, 0xF6, 0xB7, 0x2F, 0x7C, 0x8D, 0x18, 0x4E, 0x5A, 0xA8,
0x4D, 0x47, 0x5B, 0x97, 0x2B, 0x00, 0x1C, 0x20, 0x31, 0x45, 0xD3, 0x42, 0x35, 0x2B, 0x00, 0x0D,
0x21, 0x30, 0x3F, 0x4E, 0xD4, 0x44, 0x35, 0x2B, 0x01, 0x2B, 0x2C, 0x2C, 0x2B, 0x27, 0x79, 0x01,
0x1C, 0x7B, 0x54, 0xA0, 0x89, 0x3D, 0x7D, 0xC8, 0x8B, 0x69, 0x34, 0x47, 0xA4, 0x37, 0x03, 0x2B,
0x41, 0x8F, 0x56, 0x1F, 0x1F, 0x31, 0x43, 0x00, 0xDD, 0x83, 0x7E, 0x00, 0x00, 0x06, 0x00, 0x7D,
0x81, 0x89, 0x18, 0xDD, 0x84, 0x7D, 0x7A, 0x79, 0x7A, 0x79, 0x7A, 0x00, 0x77, 0x73, 0x24, 0x1E,
0xB7, 0x36, 0x25, 0x6B, 0x17, 0x57, 0x56, 0x35, 0xF0, 0x35, 0x7C, 0x79, 0x32, 0x40, 0x98, 0x5A,
0x27, 0x00, 0x3C, 0x8A, 0x62, 0x21, 0x1F, 0x2B, 0x3D, 0xAE, 0x00, 0xAE, 0x01, 0x10, 0xAB, 0xAB,
0xAB, 0xAB, 0xAD, 0xB0, 0x02, 0xB2, 0xAF, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0xA9, 0xA6, 0x04, 0x25,
0x1F, 0x7D, 0x98, 0xD1, 0x29, 0x77, 0x9C, 0x2C, 0x52, 0xB0, 0x1C, 0x6F, 0x3C, 0x70, 0x9D, 0x44,
0x56, 0xAB, 0x40, 0x00, 0x1E, 0x1E, 0x24, 0x31, 0x39, 0x3F, 0x09, 0x10, 0x06, 0x10, 0xC0, 0x40,
0x41, 0x43, 0x41, 0x3D, 0x3C, 0x3C, 0x3C, 0x00, 0x3C, 0x3B, 0x36, 0x2E, 0x24, 0x1E, 0x49, 0xA9,
0x29, 0x47, 0xC0, 0x41, 0x8D, 0x65, 0x9C, 0x33, 0x43, 0x95, 0xBB, 0xB7, 0x01, 0x7A, 0x2B, 0x62,
0x0E, 0x22, 0x28, 0x2C, 0x2B, 0x29, 0x04, 0x01, 0x00, 0x07, 0x00, 0x2B, 0x2E, 0x2E, 0x2C, 0x2D,
0xC2, 0x00, 0x83, 0x2B, 0x2B, 0x28, 0x24, 0x1F, 0x1C, 0xE9, 0xC2, 0x49, 0x50, 0xC0, 0xA5, 0x52,
0x32, 0x2F, 0x25, 0x2E, 0x41, 0x4B, 0x44, 0x01, 0x30, 0x40, 0x10, 0xD4, 0x08, 0x08, 0x10, 0x20,
0x05, 0x10, 0x1F, 0x47, 0x09, 0xAE, 0x1F, 0x20, 0x1E, 0x1E, 0x1E, 0x20, 0x1E, 0xFC, 0x55, 0x80,
0x1A, 0x41, 0x10, 0x09, 0x35, 0x3B, 0xC4, 0x83, 0x04, 0x28, 0x28, 0x26, 0x1E, 0xD9, 0x64, 0x1A,
0x28, 0xB3, 0x3D, 0xF4, 0x69, 0x0B, 0xAE, 0xC1, 0x1E, 0x26, 0x3D, 0x32, 0x51, 0x66, 0x63, 0x3F,
0x27, 0x20, 0x24, 0x26, 0x80, 0x25, 0x28, 0x05, 0x10, 0x01, 0x00, 0x2C, 0x2A, 0x29, 0xDA, 0x2E,
0x8C, 0xD5, 0x0E, 0x27, 0x22, 0x1E, 0xA1, 0xC6, 0x28, 0xC3, 0x92, 0x98, 0x14, 0xD1, 0x5F, 0xA5,
0xAC, 0xA5, 0xA5, 0xB0, 0x95, 0x3B, 0x00, 0x7D, 0x08, 0x21, 0x2B, 0x37, 0x3C, 0x40, 0x3F, 0x09,
0x00, 0x81, 0x3F, 0x41, 0x40, 0x40, 0x40, 0x40, 0x42, 0x3F, 0x00, 0x40, 0x40, 0x3F, 0x40, 0x3E,
0x38, 0x31, 0x26, 0x00, 0x1E, 0xC2, 0x4D, 0xD9, 0x41, 0x7D, 0xC8, 0x26, 0x49, 0xAB, 0x73, 0x0E,
0x4A, 0x47, 0x49, 0x51, 0x87, 0x9C, 0x0E, 0x09, 0x25, 0x40, 0x36, 0x00, 0x00, 0x07, 0x60, 0xF4,
0x00, 0x00, 0x00, 0x00, 0xF5, 0xF5, 0x36, 0xF5, 0x34, 0x84, 0x22, 0x35, 0x29, 0xA7, 0xF7, 0x33,
0x7C, 0x8C, 0x32, 0x39, 0x27, 0x26, 0x27, 0x35, 0x4B, 0x9F, 0x4B, 0x00, 0x1E, 0x1D, 0x26, 0x30,
0x40, 0x4A, 0x5F, 0x0E, 0x50, 0x40, 0x02, 0x20, 0x52, 0x0E, 0x4C, 0x2E, 0x4D, 0x45, 0x39, 0x27,
0x41, 0x70, 0x87, 0x22, 0x59, 0x0A, 0x39, 0x7D, 0xA8, 0x1A, 0x20, 0x36, 0x8A, 0x0A, 0x68, 0x27,
0x1C, 0x6F, 0x0C, 0x7D, 0x08, 0x1F, 0x1C, 0x20, 0x18, 0x29, 0x32, 0x35, 0x39, 0x38, 0x6B, 0x0C,
0xAD, 0x1F, 0x39, 0x60, 0x39, 0x39, 0xA4, 0x1F, 0x38, 0x38, 0x33, 0x2A, 0x24, 0x04, 0x1E, 0xE9,
0x82, 0xD5, 0xF5, 0x34, 0x7E, 0x81, 0x2A, 0x35, 0x02, 0x86, 0x27, 0x42, 0x9D, 0x4D, 0x20, 0x6B,
0x02, 0x20, 0x21, 0x20, 0x22, 0x21, 0x69, 0x1C, 0x23, 0xAA, 0x1F, 0x21, 0x23, 0x31, 0x01, 0x94,
0x21, 0x23, 0x21, 0x1E, 0x1E, 0x1B, 0x05, 0xC9, 0x7D, 0xB8, 0xC0, 0x2D, 0x51, 0xAA, 0x68, 0x33,
0x2F, 0x33, 0x40, 0x00, 0x85, 0x9E, 0x2E, 0x09, 0x90, 0x78, 0xF0, 0x1A, 0x69, 0xEB, 0x99, 0x7A,
0xD8, 0x38, 0x6A, 0xA6, 0xAB, 0xA6, 0xA6, 0xAF, 0x98, 0x00, 0x47, 0x24, 0x00, 0x00, 0x60, 0xF1,
0x81, 0xF4, 0x85, 0x10, 0x29, 0xC1, 0x25, 0x7C, 0x37, 0x47, 0x60, 0x73, 0x71, 0x53, 0x39, 0x25,
0x00, 0x09, 0x80, 0x34, 0xDC, 0x51, 0xE1, 0x68, 0x40, 0xEF, 0x78, 0x27, 0x2E, 0x31, 0x1F, 0x2E,
0x29, 0x72, 0xC3, 0x81, 0x70, 0xE9, 0xD2, 0x71, 0x23, 0x3E, 0x98, 0x22, 0x7C, 0x23, 0x23, 0x23,
0x22, 0x25, 0x25, 0x24, 0x24, 0x00, 0x23, 0x23, 0x20, 0x1B, 0x1A, 0x0C, 0x30, 0xB9, 0x01, 0x0E,
0x70, 0xE0, 0x1A, 0x34, 0x66, 0xC9, 0xE0, 0x1C, 0x38, 0x42, 0x63, 0x67, 0x66, 0x16, 0x67, 0x68,
0x67, 0x66, 0x68, 0x68, 0x68, 0x65, 0x00, 0x5E, 0xC5, 0xE4, 0x19, 0x35, 0xA0, 0x0D, 0x61, 0x41,
0x10, 0xD2, 0x42, 0xB0, 0x11, 0xFA, 0x36, 0xAE, 0x1F, 0x97, 0x01, 0xA8, 0x1F, 0xA9, 0x1F, 0xAD,
0xFA, 0xC9, 0xF0, 0xC5, 0x04, 0xFE, 0x41, 0x80, 0x79, 0x0C, 0x40, 0x46, 0x46, 0x46, 0x97, 0x11,
0x46, 0x43, 0x46, 0x41, 0x33, 0x80, 0xA4, 0x1A, 0xCD, 0x04, 0x1C, 0x1D, 0x28, 0x5D, 0x41, 0xE9,
0xF2, 0xC2, 0x92, 0x22, 0x9B, 0x01, 0x25, 0x00, 0x00, 0x26, 0x57, 0x26, 0x4C, 0x3E, 0x1C, 0x29,
0x80, 0x24, 0x21, 0x20, 0x1B, 0x0A, 0x09, 0x5C, 0x89, 0x5C, 0x0D, 0x71, 0xCF, 0xA9, 0x23, 0xBD,
0x33, 0x1F, 0x25, 0x2F, 0x33, 0x1E, 0xBD, 0x95, 0x23, 0x2B, 0x90, 0x63, 0xC6, 0x01, 0x84, 0x61,
0xF2, 0x51, 0x11, 0x36, 0x82, 0x19, 0x28, 0x07, 0x32, 0x85, 0x60, 0x17, 0x25, 0x23, 0x21, 0x21,
0x24, 0x34, 0x85, 0x5E, 0x00, 0x20, 0x59, 0x40, 0x1A, 0x92, 0x1B, 0x29, 0x33, 0xA7, 0x77, 0x0A,
0x27, 0x2F, 0x30, 0x19, 0xD1, 0x99, 0x22, 0x2D, 0x23, 0xE7, 0x13, 0xAA, 0x6F, 0xEA, 0x59, 0x71,
0x9E, 0x88, 0x6A, 0x67, 0x67, 0x68, 0x00, 0x6A, 0x71, 0xAB, 0x56, 0xC7, 0x90, 0x1E, 0x2A, 0x3A,
0x10, 0x41, 0x00, 0x82, 0x91, 0xF6, 0x56, 0x49, 0x29, 0x18, 0x30, 0x74, 0x4F, 0x90, 0xAA, 0x3F,
0xB1, 0xAD, 0xA7, 0x13, 0x0E, 0xA8, 0xA5, 0x74, 0x2D, 0x08, 0x1D, 0xBF, 0x81, 0x20, 0x2B, 0x3C,
0xAB, 0x79, 0x2A, 0x02, 0x1E, 0x37, 0xDA, 0x8D, 0x49, 0xD1, 0x39, 0x0C, 0x11, 0x9F, 0x10, 0x3E,
0x56, 0x3E, 0x92, 0x77, 0x4B, 0x46, 0x46, 0x45, 0x45, 0x3E, 0x00, 0x2E, 0x21, 0xE0, 0x10, 0xA2,
0x7C, 0x3D, 0x41, 0x00, 0xD9, 0x39, 0xEC, 0xC1, 0xEC, 0x19, 0x06, 0x69, 0x5B, 0x86, 0x39, 0x25,
0x34, 0x51, 0x3F, 0x29, 0x07, 0x26, 0x24, 0x24, 0x25, 0x23, 0xDB, 0xB1, 0x1F, 0x2B, 0x20, 0x39,
0xAB, 0x7A, 0x2B, 0x1F, 0x28, 0x61, 0xF9, 0x93, 0xDA, 0x60, 0x95, 0x21, 0xAA, 0x9B, 0x22, 0x23,
0x21, 0x25, 0x27, 0x25, 0x03, 0x07, 0x03, 0x86, 0xB0, 0x28, 0x36, 0xA9, 0x77, 0x28, 0x1E, 0x03,
0x1B, 0x1C, 0x33, 0x82, 0x19, 0xC9, 0x80, 0x1A, 0xA5, 0xB2, 0x2D, 0x54, 0x45, 0x78, 0x89, 0x88,
0x6C, 0x2E, 0x22, 0x86, 0xA0, 0x80, 0x1C, 0x24, 0x2D, 0x56, 0x41, 0x22, 0x07, 0x00, 0x6E, 0x4B,
0xC0, 0x9D, 0x8A, 0x2D, 0x13, 0xE4, 0xA0, 0xFD, 0x0B, 0x7B, 0xB0, 0xA5, 0x32, 0x0F, 0xA0, 0xCF,
0xB9, 0x0C, 0x26, 0x22, 0xEF, 0x26, 0x75, 0xA0, 0x55, 0x1E, 0x51, 0xD1, 0xBA, 0x0C, 0xF9, 0xA5,
0x22, 0x3F, 0x4B, 0x6B, 0xA3, 0x29, 0xFF, 0xC7, 0x1F, 0x41, 0x30, 0x47, 0x21, 0xD1, 0xA9, 0x7F,
0x2E, 0x50, 0xA5, 0x02, 0x32, 0xA5, 0x02, 0x30, 0x5F, 0xA5, 0x02, 0x1D, 0x4C, 0xE0, 0x1A, 0x9A,
0x64, 0x69, 0xCB, 0x41, 0xB0, 0x37, 0x75, 0x89, 0x67, 0x40, 0x12, 0x24, 0x3E, 0x8B, 0x62, 0x21,
0x04, 0x99, 0x67, 0x7C, 0xE0, 0x1E, 0x52, 0x19, 0x6D, 0x37, 0x28, 0xFA, 0xB0, 0x33, 0x57, 0x75,
0x8F, 0x2D, 0x1F, 0xA5, 0x32, 0x33, 0x66, 0x40, 0xF0, 0xD1, 0xA9, 0xF0, 0xDC, 0x81, 0x24, 0x9A,
0x8A, 0x2A, 0x44, 0xA4, 0x89, 0x46, 0x06, 0x37, 0x39, 0x58, 0xA5, 0x02, 0xC7, 0x00, 0x39, 0xF7,
0x41, 0xF0, 0xF9, 0x33, 0xF8, 0xD1, 0xB6, 0xA5, 0x12, 0xBA, 0xAC, 0x7D, 0x34, 0x21, 0x03, 0x30,
0x83, 0x3A, 0xF0, 0xE5, 0xF6, 0x0D, 0x71, 0x7C, 0x44, 0x31, 0x40, 0x4B, 0x50, 0x0F, 0x4D, 0x42,
0x30, 0x32, 0x3C, 0x1B, 0x3B, 0xF0, 0xC1, 0xCB, 0x35, 0x68, 0x47, 0xDA, 0x39, 0x27, 0x21, 0xD6,
0x21, 0x28, 0x32, 0x10, 0x33, 0x31, 0x28, 0x20, 0x57, 0x87, 0xFE, 0x8A, 0x0A, 0x1B, 0x19, 0x38,
0xB5, 0x93, 0xDA, 0x7D, 0x38, 0x11, 0x9A, 0x2C, 0x46, 0x7A, 0x88, 0x0D, 0x88, 0x6D, 0x2E, 0x21,
0x1C, 0xDD, 0x29, 0x26, 0x22, 0x20, 0x44, 0x05, 0x1C, 0x9E, 0x88, 0x27, 0x2D, 0x2D, 0x29, 0x68,
0x09, 0x85, 0xA1, 0x76, 0x48, 0xC9, 0x00, 0x9C, 0xB5, 0x21, 0x30, 0x7C, 0xAF, 0x0D, 0x95, 0x8E,
0x8E, 0x9A, 0xAF, 0x56, 0xD1, 0x09, 0x26, 0x40, 0x32, 0x40, 0x41, 0x38, 0x28, 0x1F, 0x62, 0x28,
0x34, 0x08, 0xC0, 0x4A, 0x0E, 0x1E, 0x28, 0x38, 0x86, 0x85, 0x81, 0x2B, 0x01, 0x80, 0x44, 0x1C,
0xB5, 0x53, 0x0E, 0x61, 0x32, 0x3C, 0x57, 0xAB, 0x56, 0x1D, 0x3E, 0x3E, 0x3E, 0x4B, 0x6C, 0xA3,
0x2A, 0xB5, 0x03, 0x80, 0x4B, 0x81, 0x14, 0x24, 0x84, 0x09, 0x29, 0x30, 0x33, 0x2E, 0x0A, 0x27,
0x46, 0x04, 0x20, 0x31, 0x52, 0x2E, 0x00, 0x3B, 0xD1, 0x49, 0xA2, 0x1C, 0x1A, 0x91, 0x45, 0x9E,
0xBA, 0x32, 0x84, 0x7C, 0x33, 0x0C, 0x22, 0x23, 0x24, 0x2F, 0x48, 0x98, 0x56, 0x1E, 0x00, 0x21,
0x39, 0x81, 0x24, 0xF0, 0x03, 0x29, 0x3A, 0xA0, 0xB6, 0x0C, 0xB4, 0x5D, 0xC5, 0x01, 0x21, 0x3B,
0x65, 0x2E, 0x00, 0x48, 0x44, 0x55, 0x8E, 0x85, 0x20, 0xD1, 0xA4, 0x20, 0x38, 0x8A, 0x67, 0x25,
0x07, 0xBA, 0x00, 0x24, 0x3F, 0x8B, 0x62, 0x20, 0x21, 0x3F, 0x01, 0xF5, 0x27, 0x85, 0x00, 0x2F,
0x4F, 0x8E, 0x09, 0x85, 0x2A, 0x1E, 0x13, 0x19, 0x22, 0x3E, 0x6F, 0x6E, 0x24, 0x1C, 0x61, 0xB2,
0x8B, 0xA4, 0xD0, 0x1F, 0x33, 0x75, 0x8E, 0x2E, 0x1E, 0x1D, 0x1E, 0x00, 0x2B, 0x47, 0xAB, 0x41,
0x1E, 0xD9, 0x31, 0x4F, 0x2A, 0x20, 0x1C, 0x20, 0x35, 0x5F, 0x41, 0x00, 0x8C, 0x30, 0x20, 0x10,
0x1B, 0x22, 0x41, 0x40, 0xB5, 0xC3, 0x0E, 0x71, 0x8E, 0x25, 0x44, 0xA5, 0x3C, 0x89, 0x45, 0x37,
0x39, 0x59, 0x9E, 0x8A, 0x2B, 0x00, 0x1B, 0x23, 0x41, 0x10, 0x10, 0x4E, 0x41, 0x00, 0x37, 0x85,
0x10, 0xA8, 0x8E, 0x32, 0x20, 0xD2, 0x16, 0xB6, 0x20, 0x39, 0xC8, 0xA5, 0x22, 0x5D, 0x83, 0xF8,
0x55, 0x8E, 0xB1, 0xBC, 0xBC, 0xAD, 0x7E, 0x36, 0x00, 0xD5, 0x05, 0x85, 0x30, 0x29, 0x85, 0x50,
0x32, 0x1F, 0x1B, 0x23, 0x0B, 0x3A, 0x25, 0x50, 0x95, 0x81, 0x45, 0xBD, 0x1A, 0xC0, 0x20, 0x23,
0x2F, 0x2D, 0x40, 0x4B, 0x4E, 0x4C, 0x41, 0x30, 0x23, 0x1C, 0x00, 0x10, 0x40, 0x50, 0x2B, 0x48,
0x02, 0x65, 0x41, 0x20, 0x8E, 0x16, 0xA2, 0x23, 0xE9, 0xB1, 0xA7, 0xDC, 0x7D, 0x48, 0xC0, 0x96,
0x24, 0x27, 0x29, 0x27, 0x0D, 0x25, 0x1F, 0x1D, 0x19, 0x16, 0xB5, 0x43, 0x1F, 0x39, 0x66, 0x18,
0x41, 0x00, 0x90, 0x33, 0x1F, 0xA2, 0x63, 0x1A, 0xA1, 0x86, 0xE9, 0x62, 0xD1, 0xF3, 0x47, 0x22,
0x24, 0x25, 0x1F, 0x1E, 0x22, 0x2C, 0x01, 0x31, 0x2C, 0x26, 0x5A, 0x1A, 0xC9, 0x20, 0x53, 0x30,
0x22, 0x18, 0x27, 0x3F, 0x6B, 0xBA, 0x08, 0x93, 0x39, 0x26, 0x21, 0x08, 0x28, 0x46, 0x73, 0xC9,
0xA0, 0x1C, 0xD5, 0x05, 0x99, 0x0E, 0xB7, 0x54, 0xE8, 0x49, 0x28, 0x34, 0x78, 0x89, 0x6D, 0x34,
0x46, 0x8F, 0x01, 0xB0, 0xAB, 0x86, 0x29, 0x1D, 0x1B, 0xB5, 0x33, 0x69, 0x40, 0x49, 0x3C, 0x41,
0x55, 0x76, 0x11, 0x0A, 0x9E, 0x52, 0x20, 0x3F, 0x3C, 0x43, 0x5B, 0x7D, 0x85, 0x40, 0x1C, 0xD9,
0x81, 0xA0, 0x29, 0x2E, 0x83, 0x22, 0x3B, 0xA5, 0x9C, 0x8F, 0xA0, 0x02, 0x9A, 0x93, 0x87, 0x5A,
0x66, 0xA1, 0x86, 0x24, 0x00, 0x81, 0x44, 0xC4, 0xC1, 0x07, 0x00, 0x14, 0x1A, 0xD5, 0xC2, 0xBF,
0x19, 0xBE, 0xBF, 0xC3, 0xC5, 0x2E, 0x00, 0x50, 0x41, 0x60, 0x1A, 0x50, 0xD1, 0x79, 0x72, 0x43,
0x2D, 0x6C, 0x99, 0x47, 0x43, 0x54, 0x03, 0x9E, 0xA1, 0x3E, 0x30, 0x3D, 0x5C, 0xAA, 0x2C, 0x00,
0x1D, 0x02, 0x6F, 0x41, 0xF0, 0xFF, 0x4E, 0x22, 0xD1, 0xD9, 0xA5, 0x83, 0x8A, 0x75, 0x69, 0x2E,
0x28, 0x3C, 0x74, 0x8A, 0x2D, 0x1E, 0x00, 0x2A, 0x48, 0xA3, 0x41, 0x00, 0x3E, 0xD9, 0x11, 0xFF,
0x3D, 0xF0, 0xA8, 0x4C, 0x2A, 0x59, 0xAA, 0x39, 0x45, 0x8D, 0x23, 0x39, 0x8A, 0x14, 0x63, 0x24,
0x20, 0x32, 0x6C, 0x87, 0x27, 0x1A, 0x00, 0x24, 0x43, 0xA5, 0x2F, 0x51, 0x01, 0x61, 0xE9, 0xF2,
0xFF, 0x50, 0x3E, 0x21, 0xD5, 0xB5, 0x3D, 0x84, 0x22, 0x3A, 0x89, 0x66, 0x28, 0x07, 0x26, 0x34,
0x6D, 0x89, 0x2E, 0x21, 0x2B, 0x48, 0x00, 0xA5, 0x31, 0xE1, 0x0A, 0x4A, 0x96, 0xA0, 0x00, 0x00,
0xA2, 0x44, 0xA3, 0xA1, 0x01, 0x10, 0xA2, 0xA2, 0xA2, 0xA2, 0xA3, 0x04, 0xA2, 0xA2, 0xA0, 0x9A,
0x8B, 0x37, 0xAD, 0x9B, 0x35, 0x0C, 0xC0, 0x29, 0x9B, 0x61, 0xD5, 0x04, 0x8C, 0x84, 0x66, 0x64,
0x6D, 0x06, 0x8A, 0x9A, 0x68, 0x63, 0x68, 0x72, 0xAB, 0x2E, 0x00, 0x1B, 0x1F, 0x29, 0x08, 0x53,
0x55, 0x50, 0x4E, 0x4D, 0x04, 0x4C, 0x01, 0x10, 0x00, 0x00, 0x4D, 0x4D, 0x4D, 0x4C, 0x4D, 0x06,
0x4A, 0x43, 0x37, 0x29, 0x20, 0x69, 0xCB, 0x31, 0x80, 0x31, 0x60, 0x6C, 0x8C, 0x8A, 0x8A, 0x8C,
0x90, 0x8F, 0x8B, 0x00, 0x8A, 0x8B, 0x8D, 0x89, 0xF6, 0x0F, 0x27, 0x3A, 0x4A, 0x10, 0x4F, 0x47,
0x38, 0x2E, 0x01, 0x10, 0x9D, 0x01, 0x28, 0x29, 0x30, 0x29, 0x28, 0x2A, 0x29, 0x2A, 0x29, 0x27,
0x23, 0x00, 0x1F, 0xA1, 0xB6, 0x3A, 0x09, 0x95, 0x25, 0x32, 0x39, 0x3A, 0x0A, 0x3B, 0x39, 0x3C,
0x3D, 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x31, 0x21, 0xA1, 0x06, 0x4D, 0x41, 0x00, 0x38, 0x26, 0x1D,
0x14, 0x1D, 0x02, 0x00, 0xB4, 0x04, 0x1C, 0x1C, 0x1D, 0x1E, 0x1D, 0x06, 0x1C, 0x1D, 0xB6, 0x01,
0xF5, 0xC7, 0x81, 0xA4, 0x4C, 0x03, 0x01, 0x10, 0x22, 0x7C, 0x40, 0x03, 0x20, 0x75, 0x01, 0x3A,
0x89, 0x1D, 0x44, 0x1F, 0x50, 0x18, 0xF0, 0xD5, 0x95, 0x51, 0x0D, 0x91, 0x85, 0xD0, 0x3F, 0x6D,
0x71, 0x13, 0x2A, 0xF8, 0x95, 0xA7, 0xA8, 0x00, 0x54, 0x20, 0x01, 0x9D, 0x51, 0x71, 0x21, 0xF0,
0xA9, 0x5F, 0x4E, 0xC0, 0x1C, 0x7F, 0xAD, 0xBE, 0xB5, 0x33, 0x19, 0x94, 0x50, 0x1C, 0xA0, 0xD9,
0x11, 0x6F, 0x78, 0x4F, 0xBB, 0xD1, 0xF7, 0xB1, 0xB7, 0x04, 0x3E, 0x74, 0x97, 0x1A, 0x1E, 0x30,
0x85, 0x40, 0x5B, 0x6F, 0x38, 0x2A, 0x2B, 0x03, 0x30, 0x2A, 0x2B, 0x29, 0x2A, 0x08, 0x2A, 0x2A,
0x28, 0x29, 0x24, 0x20, 0x1C, 0x71, 0x93, 0x80, 0xE5, 0xF6, 0x7D, 0x8A, 0x21, 0x3F, 0x73, 0x5A,
0x4F, 0x4F, 0x50, 0x07, 0x4F, 0x01, 0x00, 0x4E, 0x4F, 0x4F, 0x4E, 0x50, 0x50, 0x02, 0x4F, 0x4D,
0x46, 0x38, 0x28, 0x20, 0x51, 0x41, 0x1C, 0x40, 0x71, 0x73, 0x1C, 0x3E, 0x31, 0x0B, 0x04, 0x20,
0x1D, 0xAB, 0x57, 0x24, 0x4D, 0x68, 0x5E, 0xFF, 0x3D, 0xF0, 0x3A, 0x24, 0x1B, 0x55, 0x9E, 0x3B,
0x45, 0xD9, 0xA1, 0x7C, 0x6C, 0x2B, 0x20, 0x7D, 0x23, 0x30, 0x53, 0x21, 0x49, 0x09, 0x21, 0x11,
0x0E, 0x40, 0xF0, 0xA5, 0x12, 0xE8, 0x71, 0x1F, 0x34, 0x3D, 0x21, 0x3F, 0x7F, 0x41, 0xDE, 0x1E,
0xAB, 0x9E, 0x40, 0x24, 0x1C, 0x07, 0x1E, 0x27, 0x3B, 0x85, 0xAF, 0x6E, 0x95, 0x01, 0x24, 0x2E,
0xC0, 0xFF, 0x21, 0xFB, 0x47, 0x89, 0x2D, 0x85, 0x80, 0x01, 0x10, 0x19, 0xFB, 0x53, 0xBA, 0x4E,
0x8E, 0xB4, 0x6F, 0x30, 0x33, 0x57, 0xA5, 0x00, 0xA0, 0x50, 0x2F, 0x21, 0x85, 0x40, 0x03, 0x30,
0x03, 0x30, 0x00, 0x00, 0xF0, 0x63, 0x0F, 0xDF, 0x3D, 0x25, 0xD9, 0x91, 0xDC, 0x3B, 0x28, 0x11,
0x2C, 0x84, 0x1D, 0x24, 0x30, 0x45, 0x65, 0xA7, 0xA1, 0x01, 0x8B, 0xB1, 0x78, 0x3E, 0x2A, 0x78,
0x07, 0x22, 0x89, 0x2D, 0xA0, 0x7D, 0x6E, 0x05, 0x30, 0x66, 0x01, 0x00, 0x65, 0x66, 0x66, 0x14,
0x66, 0x63, 0x59, 0x46, 0x30, 0x1F, 0x1C, 0xD9, 0xA1, 0x80, 0xED, 0x5F, 0x19, 0xCB, 0x4D, 0x4A,
0x76, 0xB6, 0xBB, 0x88, 0x05, 0x43, 0x5B, 0x23, 0xCD, 0x3D, 0x64, 0x44, 0x3A, 0x39, 0x06, 0x00,
0x86, 0x00, 0x00, 0x39, 0x38, 0x3A, 0x39, 0x38, 0x38, 0x38, 0x01, 0x32, 0x2B, 0x22, 0xC8, 0x20,
0x19, 0x6D, 0x77, 0x1C, 0xE5, 0x95, 0xA8, 0x27, 0x3B, 0x88, 0xB2, 0x8F, 0x79, 0xAC, 0x9F, 0x00,
0x41, 0x1A, 0x16, 0x23, 0xD0, 0x2C, 0x52, 0x2F, 0x20, 0x20, 0x0A, 0x1F, 0x1F, 0x20, 0x22, 0x21,
0x0C, 0x06, 0x1F, 0x21, 0x20, 0x1F, 0x20, 0x20, 0x20, 0x36, 0x01, 0x5D, 0x96, 0x95, 0xB1, 0x20,
0x70, 0x2F, 0x55, 0xA5, 0xA0, 0x5D, 0x3F, 0x3F, 0x51, 0x00, 0x8F, 0xB6, 0x6F, 0x2B, 0x1E, 0x58,
0x5D, 0x2B, 0x31, 0xD5, 0xA0, 0xB7, 0x22, 0xD6, 0x24, 0x19, 0x6D, 0xE7, 0x1E, 0x2A, 0x72, 0xB0,
0x0B, 0x77, 0x3E, 0x2B, 0x23, 0x24, 0x30, 0x47, 0x6F, 0x00, 0xAB, 0x9B, 0x24, 0xD0, 0x0C, 0x04,
0x1C, 0x4D, 0xE3, 0x08, 0x14, 0x9C, 0xD8, 0x21, 0x23, 0x20, 0x1E, 0x61, 0x92, 0x46, 0xDC, 0x39,
0x10, 0x27, 0x95, 0x95, 0x6F, 0x4D, 0x32, 0x9F, 0x1A, 0x1F, 0x2A, 0x22, 0x3B, 0x4A, 0x86, 0x26,
0x8D, 0x09, 0xA5, 0x12, 0x46, 0xEB, 0x80, 0xB0, 0x1C, 0x1E, 0x26, 0x2E, 0x36, 0x3A, 0x48, 0x29,
0x00, 0x1E, 0xC1, 0xB8, 0x4E, 0x46, 0x07, 0x30, 0x27, 0x26, 0x2E, 0x36, 0x1D, 0x4E, 0x23, 0x2B,
0x2B, 0x20, 0x50, 0x06, 0x4F, 0xBF, 0xC0, 0x10, 0xB9, 0x38, 0x10, 0x30, 0x1A, 0x19, 0x1C, 0x1E,
0x23, 0x04, 0x2A, 0xED, 0x03, 0x87, 0xC3, 0xF7, 0x36, 0xD1, 0x89, 0x34, 0x42, 0x41, 0xB0, 0x04,
0x08, 0x01, 0x71, 0x57, 0x15, 0x27, 0x37, 0x47, 0x48, 0x0F, 0x3E, 0x2B, 0x20, 0x11, 0x3E, 0x10,
0x26, 0x2F, 0x3A, 0x49, 0x0C, 0x69, 0xAC, 0x1B, 0x17, 0x43, 0xD8, 0x70, 0x0D, 0x31, 0xAC, 0x9F,
0x29, 0x74, 0x2D, 0xB1, 0x0B, 0x2E, 0x2E, 0x4D, 0x35, 0x2C, 0x18, 0x2A, 0x2B, 0x32, 0x28, 0xE0,
0x12, 0x1E, 0x20, 0x24, 0x2B, 0x36, 0x45, 0x02, 0x55, 0xA1, 0xD2, 0x3F, 0x30, 0x49, 0x27, 0xD1,
0xF9, 0x1B, 0x48, 0xF0, 0x5F, 0x78, 0xA4, 0xA5, 0xA6, 0xA4, 0xA4, 0xA5, 0x01, 0xA5, 0xA6, 0xA6,
0xA5, 0xA2, 0x19, 0x00, 0x1D, 0xB8, 0x00, 0xA0, 0x1C, 0x1C, 0x11, 0x05, 0x28, 0x32, 0x3D, 0x4E,
0x7B, 0x04, 0xC9, 0x10, 0x52, 0xFF, 0x42, 0x3D, 0x84, 0xB5, 0x53, 0x19, 0x49, 0x45, 0xB2, 0x28,
0x54, 0x6F, 0x72, 0x72, 0x72, 0x72, 0x73, 0x00, 0x79, 0x82, 0x9B, 0xBB, 0x8B, 0x99, 0x58, 0x21,
0x26, 0x20, 0x2F, 0x38, 0x4A, 0x68, 0xAD, 0xE1, 0x5C, 0x52, 0xDD, 0x40, 0xB1, 0x63, 0xD8, 0x0A,
0x1B, 0x19, 0x69, 0x9B, 0xF9, 0x97, 0x29, 0x64, 0x31, 0x71, 0x07, 0x38, 0x44, 0x62, 0xA5, 0xAD,
0x6E, 0x02, 0x37, 0x20, 0x69, 0x19, 0x1F, 0x24, 0x2B, 0x35, 0x42, 0x04, 0x54, 0x96, 0xD2, 0xA8,
0x52, 0xF8, 0xB4, 0x7D, 0x5E, 0x08, 0x4B, 0x37, 0x27, 0x20, 0xD0, 0x6C, 0x21, 0xD1, 0x29, 0xDE,
0x01, 0xD0, 0x19, 0x17, 0x6A, 0x23, 0x09, 0x28, 0x39, 0x78, 0xB6, 0x8F, 0x06, 0x45, 0x2F, 0x82,
0x10, 0x1E, 0x24, 0x30, 0x3C, 0x4C, 0x04, 0x79, 0xC0, 0xF4, 0x12, 0xD7, 0x25, 0x85, 0x00, 0x6A,
0x49, 0x35, 0x1C, 0x2B, 0x22, 0x20, 0xA9, 0x9F, 0x48, 0xE9, 0xE2, 0x20, 0x2C, 0x28, 0x4D, 0x9F,
0xAC, 0x67, 0x38, 0x25, 0x1E, 0x08, 0x2A, 0x80, 0x37, 0x50, 0xAB, 0x6C, 0x52, 0xF1, 0xCD, 0x9B,
0x0D, 0x01, 0x88, 0xE3, 0x4F, 0x2F, 0x1F, 0x80, 0x28, 0x19, 0xF6, 0xBE, 0x62, 0x26, 0x70, 0x37,
0x76, 0xB6, 0x8E, 0x41, 0x2E, 0x22, 0xB9, 0x40, 0x80, 0x51, 0x10, 0x51, 0xD3, 0x94, 0x6A, 0x63,
0x74, 0xA4, 0x02, 0x41, 0x00, 0x48, 0x55, 0x20, 0x09, 0xD5, 0xF0, 0x9F, 0x2C, 0x4E, 0xA1, 0x1D,
0xA7, 0x63, 0x3D, 0x2C, 0x25, 0x22, 0x21, 0x21, 0x00, 0x37, 0x03, 0x21, 0x3A, 0x64, 0xCF, 0x20,
0xD6, 0xAC, 0x7A, 0x11, 0x63, 0x4E, 0x40, 0x3F, 0x5A, 0xA3, 0x41, 0x20, 0xEB, 0x8F, 0xC0, 0x61,
0x22, 0x05, 0x09, 0x27, 0x19, 0x81, 0x2B, 0x6F, 0xB6, 0xA5, 0x0B, 0x7D, 0x72, 0x6A, 0x68, 0x68,
0x67, 0x68, 0x65, 0x00, 0x5D, 0x22, 0xB5, 0x23, 0x98, 0x25, 0xB5, 0x7D, 0x59, 0x42, 0x0C, 0x36,
0x37, 0x53, 0xA2, 0x85, 0x00, 0x45, 0xBA, 0x33, 0xA1, 0xA6, 0xD0, 0xE9, 0x92, 0x1E, 0x2F, 0x82,
0xAA, 0xAB, 0xA8, 0xA7, 0x01, 0xA7, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA2, 0x24, 0x00, 0x74, 0x04,
0x5D, 0xD1, 0x50, 0xDA, 0xA8, 0x60, 0x4D, 0x63, 0x05, 0x41, 0x00, 0xE1, 0x22, 0x02, 0xB8, 0xB2,
0x2D, 0x23, 0xA4, 0x86, 0x27, 0x39, 0x3D, 0x4A, 0x4A, 0x47, 0x46, 0x45, 0x46, 0x46, 0x46, 0x00,
0x46, 0x42, 0x35, 0x23, 0x79, 0x0C, 0x44, 0x65, 0x99, 0x10, 0xD5, 0xD1, 0x40, 0xF8, 0xD2, 0xAC,
0xA5, 0xFF, 0xFF, 0x02, 0xE2, 0x9A, 0x71, 0x21, 0x5F, 0x59, 0x8A, 0x98, 0x30, 0x25, 0x02, 0x10,
0x26, 0x5E, 0x24, 0x26, 0x25, 0x24, 0xB1, 0x12, 0x21, 0x2D, 0x3F, 0x10, 0x53, 0x65, 0x74, 0xB5,
0x69, 0x0F, 0x3B, 0x64, 0x5A, 0x39, 0x30, 0x29, 0x21, 0x3B, 0x44, 0x1B, 0x95, 0xF1, 0x89, 0xC5,
0xD0, 0x30, 0x25, 0x74, 0x2D, 0x39, 0x48, 0x59, 0x6C, 0x8F, 0xC5, 0xF1, 0x00, 0x44, 0x40, 0xF8,
0xCB, 0x83, 0x49, 0x39, 0x2B, 0xB3, 0x83, 0x81, 0x21, 0x33, 0xBD, 0x3C, 0xC7, 0xF0, 0x5E, 0x91,
0x29, 0x32, 0x40, 0x1C, 0x4F, 0x61, 0x72, 0xA4, 0xD6, 0x66, 0x12, 0x63, 0x22, 0xC3, 0x60, 0x74,
0x2E, 0x2C, 0x03, 0x35, 0xFC, 0x8C, 0x45, 0x42, 0x80, 0xB4, 0x84, 0x26, 0x7C, 0x2B, 0x37, 0x43,
0x55, 0x67, 0x82, 0xB5, 0xE3, 0x00, 0x69, 0x53, 0x3C, 0xF8, 0x70, 0x21, 0x3D, 0x44, 0x69, 0x9B,
0x64, 0x7D, 0x28, 0x94, 0xF5, 0x21, 0x27, 0x2F, 0x3B, 0x49, 0x5B, 0x6E, 0x8E, 0x00, 0xCD, 0xF2,
0x1B, 0x22, 0x46, 0x85, 0x50, 0x2D, 0x13, 0xF9, 0xE3, 0x30, 0xD4, 0xF4, 0x88, 0x62, 0x20, 0x22,
0x2A, 0x33, 0x40, 0x50, 0x62, 0x01, 0x74, 0xAC, 0xD5, 0x0D, 0x21, 0xC9, 0x80, 0x95, 0xC1, 0x25,
0x37, 0x25, 0x78, 0x29, 0x28, 0x29, 0x28, 0x27, 0x00, 0x13, 0x1F, 0x21, 0x20, 0x21, 0x20, 0x1D,
0xD7, 0x5B, 0x1E, 0x1E, 0x25, 0x2D, 0x08, 0x37, 0x45, 0x57, 0x6C, 0x86, 0xB5, 0xE7, 0x45, 0x00,
0x82, 0x22, 0x45, 0x9D, 0x24, 0xCB, 0x51, 0x82, 0x88, 0x76, 0x0C, 0x86, 0x47, 0x82, 0x23, 0x94,
0x06, 0x2F, 0x6C, 0x2E, 0x25, 0x2F, 0x82, 0x84, 0x1E, 0x21, 0x2A, 0x38, 0x4F, 0x6B, 0x7F, 0xCE,
0x00, 0x3F, 0x25, 0x9B, 0xA1, 0x16, 0x0D, 0x72, 0x3D, 0x24, 0x56, 0xAF, 0x93, 0x1E, 0x76, 0x6B,
0x6B, 0x6A, 0x69, 0x60, 0x24, 0x01, 0x0E, 0x80, 0x43, 0xF6, 0x87, 0x3B, 0x28, 0x1E, 0x1D, 0x97,
0x40, 0x80, 0xC5, 0x10, 0x39, 0x55, 0x9E, 0xF1, 0xB5, 0x93, 0x22, 0x59, 0xFA, 0xA1, 0x1F, 0x32,
0x84, 0x80, 0x42, 0x34, 0xC9, 0x10, 0x25, 0x40, 0xB4, 0x06, 0x38, 0x1C, 0x05, 0xA8, 0x42, 0x2B,
0x21, 0x3E, 0x56, 0x85, 0x22, 0x2B, 0x3E, 0x5A, 0xC2, 0x41, 0x20, 0xF1, 0x7B, 0x59, 0x6A, 0xE0,
0x76, 0x8D, 0x8A, 0x68, 0x2A, 0x39, 0x02, 0x20, 0x1E, 0x1C, 0x11, 0x2D, 0x03, 0x3C, 0x69, 0x0F,
0x00, 0xCD, 0x46, 0x2E, 0xC8, 0x3F, 0x89, 0x1E, 0x25, 0x32, 0x49, 0x7F, 0x4A, 0x21, 0x49, 0x29,
0x20, 0xA5, 0xC2, 0x81, 0xA4, 0x1F, 0x30, 0x6B, 0x88, 0x2D, 0x1E, 0x03, 0xBD, 0x5D, 0x3A, 0xD8,
0x14, 0xFF, 0xE0, 0x5C, 0x30, 0x23, 0x05, 0x1D, 0x47, 0x02, 0x28, 0x3A, 0x55, 0xB9, 0x82, 0x20,
0xF1, 0x42, 0x40, 0x25, 0xF9, 0xA3, 0x3B, 0x25, 0xCB, 0x28, 0x45, 0x9A, 0x14, 0x83, 0x43, 0x2F,
0x2E, 0x2F, 0x2D, 0x26, 0x1D, 0x02, 0x80, 0x33, 0x59, 0x90, 0x20, 0xE9, 0x6E, 0x34, 0x26, 0x1F,
0x04, 0x22, 0x2F, 0x44, 0x70, 0xDB, 0x82, 0x20, 0xCB, 0x65, 0x20, 0x35, 0x21, 0x85, 0xB0, 0x28,
0x62, 0xB2, 0x27, 0x47, 0x9A, 0x14, 0xBC, 0xA6, 0xA5, 0xA4, 0xA4, 0xA3, 0xA0, 0x24, 0x00, 0xCC,
0x00, 0x42, 0x68, 0xB4, 0x09, 0x20, 0x82, 0x3D, 0x34, 0x11, 0x3A, 0x51, 0x9A, 0x37, 0x20, 0xF8,
0xA9, 0x57, 0x3A, 0x08, 0x27, 0x1E, 0xA5, 0x82, 0x15, 0xBA, 0xEF, 0x2B, 0x75, 0xA2, 0x55, 0x1C,
0x47, 0x43, 0x43, 0x42, 0x3E, 0x32, 0x22, 0xCE, 0x01, 0x80, 0x2C, 0x45, 0x67, 0x9B, 0x57, 0x11,
0xFF, 0xAB, 0x59, 0x10, 0x72, 0xCC, 0x7F, 0x20, 0xDC, 0x78, 0x4C, 0x34, 0xAE, 0x40, 0x84, 0xE9,
0xF2, 0xDB, 0x3B, 0x1F, 0x36, 0x8B, 0x6C, 0x30, 0x26, 0x03, 0x26, 0x24, 0x24, 0x24, 0x22, 0x17,
0x10, 0x22, 0x2B, 0x20, 0x3F, 0x5F, 0x8F, 0xEA, 0x03, 0x10, 0xD4, 0xE9, 0x3C, 0x10, 0x90, 0xF9,
0xBB, 0x5D, 0x41, 0x2E, 0xC7, 0x9A, 0x19, 0x22, 0x20, 0xE9, 0x12, 0x85, 0x10, 0x76, 0x9D, 0x79,
0x6F, 0xEF, 0x8C, 0x77, 0x03, 0x3B, 0x67, 0x59, 0x83, 0xDD, 0x4B, 0x51, 0xE3, 0x86, 0x50, 0x37,
0x08, 0x29, 0xF4, 0x4D, 0x1C, 0x6E, 0x33, 0x22, 0x19, 0x06, 0x25, 0x4B, 0xB2, 0x67, 0xEA, 0x2E,
0x51, 0x98, 0x47, 0x31, 0x2F, 0x2F, 0x30, 0x00, 0x2D, 0x26, 0x28, 0x3A, 0x1F, 0x27, 0x37, 0x52,
0x74, 0x04, 0xCD, 0x06, 0x31, 0xC4, 0x66, 0x45, 0xEA, 0x06, 0xFD, 0xC2, 0x19, 0x26, 0xE2, 0x71,
0xB3, 0x2C, 0x6E, 0xA3, 0xB6, 0xA6, 0xA6, 0xA4, 0x01, 0xA6, 0xA4, 0xA1, 0xAE, 0x02, 0x5D, 0x09,
0x20, 0x21, 0x28, 0x18, 0x35, 0x50, 0x70, 0xB5, 0xC1, 0x10, 0xEA, 0x83, 0x51, 0x10, 0x34, 0x26,
0xC0, 0x0C, 0x57, 0x03, 0x79, 0x8B, 0xF5, 0x37, 0x61, 0x53, 0x1A, 0x7C, 0xC1, 0x01, 0x1D, 0x28,
0x55, 0x73, 0x77, 0x74, 0x71, 0x01, 0x71, 0x73, 0x71, 0x65, 0x24, 0x1B, 0x1C, 0x1F, 0x00, 0x26,
0x2C, 0x30, 0x33, 0x35, 0x39, 0x47, 0x5E, 0x00, 0x7B, 0x9C, 0x42, 0x20, 0x69, 0x41, 0x36, 0x24,
0x00, 0x2F, 0x44, 0x27, 0x68, 0x10, 0x49, 0x99, 0x6D, 0xC7, 0x1F, 0x26, 0x32, 0x34, 0x0E, 0x33,
0x3C, 0x04, 0x32, 0xB1, 0x01, 0x1E, 0x29, 0x39, 0x86, 0x0A, 0x8E, 0x90, 0x90, 0x90, 0x94, 0x9A,
0xA3, 0xA4, 0x00, 0xAD, 0xC4, 0x04, 0xFF, 0xEA, 0x98, 0x92, 0x8F, 0x91, 0x02, 0x8F, 0x8A, 0x80,
0x2B, 0x1F, 0xCE, 0x00, 0xE9, 0xF2, 0x3A, 0x84, 0xE0, 0x25, 0x27, 0x2A, 0x28, 0x25, 0x62, 0x0B,
0xB1, 0x07, 0x51, 0x60, 0x41, 0xF0, 0xFF, 0xC6, 0x21, 0x97, 0x20, 0x15, 0x5A, 0xE5, 0x56, 0xCC,
0x7A, 0x2B, 0x7D, 0x45, 0x79, 0x89, 0x87, 0x6E, 0x2C, 0x75, 0x0C, 0x21, 0x40, 0x39, 0x63, 0x01,
0x10, 0x3D, 0xF0, 0x44, 0x28, 0x69, 0xBB, 0x28, 0x4C, 0x35, 0xC9, 0x31, 0x7B, 0xB1, 0x94, 0x8E,
0x8E, 0x9A, 0x01, 0xB0, 0x56, 0xA8, 0x01, 0x39, 0x62, 0x01, 0x10, 0x39, 0xF4, 0x45, 0x64, 0x27,
0x1B, 0xA1, 0x76, 0x46, 0xDB, 0x59, 0x1A, 0x2B, 0x93, 0x28, 0x64, 0x57, 0xAB, 0x56, 0x40, 0x3D,
0x3F, 0x4B, 0x6C, 0x00, 0xA3, 0x2A, 0x1D, 0x20, 0x30, 0x4E, 0xC1, 0x05, 0x10, 0x80, 0xC5, 0xC5,
0xC5, 0xC5, 0xC4, 0xC5, 0xC6, 0x00, 0x00, 0x80, 0xC5, 0xC6, 0xC5, 0xC4, 0xC4, 0xC2, 0xB9, 0x39,
0x00, 0x0D, 0x91, 0x4D, 0x15, 0x50, 0x85, 0x56, 0x1A, 0x83, 0x7C, 0x33, 0x24, 0x0F, 0x25, 0x24,
0x2F, 0x48, 0x98, 0x56, 0x1E, 0x1E, 0x00, 0x29, 0x38, 0x4B, 0x59, 0x5B, 0x59, 0x01, 0x00, 0x03,
0x00, 0xC0, 0x5A, 0x5B, 0x59, 0x5A, 0x5A, 0x5B, 0x5B, 0x5B, 0x00, 0x5C, 0x5D, 0x53, 0x41, 0x2D,
0x1F, 0x1B, 0x1A, 0x00, 0x91, 0xB5, 0x6A, 0xA8, 0x37, 0x8A, 0x66, 0x24, 0x33, 0x00, 0x24, 0x43,
0x40, 0x8C, 0x62, 0x4B, 0x00, 0x30, 0x3D, 0x41, 0x3F, 0x08, 0x39, 0x33, 0x30, 0x30, 0x31, 0x32,
0x31, 0x32, 0x00, 0x30, 0x32, 0x30, 0x32, 0x32, 0x31, 0x38, 0x40, 0x00, 0x48, 0x46, 0x38, 0x29,
0x1F, 0x99, 0x80, 0x51, 0x51, 0x8E, 0x86, 0xE0, 0x74, 0x8F, 0x2E, 0x1E, 0x1D, 0x1E, 0x2B, 0x47,
0x00, 0xAB, 0x41, 0x20, 0x1F, 0x29, 0x3A, 0x87, 0x87, 0x00, 0x81, 0x2F, 0x24, 0xE1, 0x07, 0x24,
0x26, 0x27, 0x26, 0x08, 0x22, 0x8C, 0x02, 0x21, 0x2E, 0x41, 0xB7, 0xB8, 0xB3, 0x02, 0x32, 0x22,
0x9B, 0x50, 0x0D, 0x31, 0x29, 0x8E, 0x20, 0x18, 0x52, 0x1D, 0x6C, 0x2B, 0x45, 0xA5, 0x89, 0x45,
0x37, 0x3B, 0x59, 0x00, 0x9E, 0x8A, 0x2B, 0x1B, 0x8E, 0x00, 0x10, 0x00, 0x3B, 0x26, 0x30, 0x05,
0x02, 0x2B, 0x36, 0x39, 0x35, 0x28, 0x1F, 0x2E, 0x12, 0x81, 0x59, 0x2E, 0x00, 0x3F, 0x24, 0x5D,
0x86, 0x45, 0x51, 0x51, 0x81, 0x81, 0xD2, 0x55, 0x8D, 0xB0, 0xBC, 0xBC, 0xAC, 0x7D, 0xE5, 0x06,
0x80, 0x22, 0xC1, 0x28, 0x48, 0x28, 0x1B, 0x1E, 0x28, 0x3F, 0x02, 0xC0, 0xDE, 0xDD, 0x70, 0x27,
0x85, 0x00, 0x3B, 0x68, 0x20, 0x2E, 0x00, 0x49, 0x58, 0x19, 0x1A, 0x84, 0x43, 0xD9, 0x21, 0x42,
0xBA, 0x9D, 0x05, 0xF5, 0x4B, 0x4F, 0x4D, 0x42, 0x31, 0x24, 0x4A, 0x09, 0x3E, 0x40, 0x20, 0x11,
0x4D, 0x28, 0x1C, 0x1E, 0x31, 0x53, 0x41, 0x00, 0x81, 0x87, 0x2E, 0x51, 0x01, 0x3E, 0x6E, 0xB6,
0x10, 0x50, 0x10, 0x1A, 0x64, 0x71, 0x43, 0x48, 0xB5, 0x13, 0x81, 0xA4, 0xE9, 0x06, 0x24, 0x25,
0x45, 0x17, 0x9D, 0x1F, 0x1E, 0x1D, 0x23, 0x3F, 0x10, 0x20, 0x2A, 0x1C, 0x20, 0x20, 0x36, 0x61,
0x41, 0x00, 0x8F, 0x30, 0x1F, 0x1B, 0x08, 0x21, 0x82, 0x21, 0x4F, 0x2B, 0x1C, 0x1A, 0xD5, 0xF5,
0x1B, 0x42, 0x1D, 0x62, 0x5D, 0x41, 0x9B, 0x01, 0x19, 0x1E, 0x27, 0x5D, 0x09, 0x4F, 0x1E, 0x21,
0x41, 0x10, 0x30, 0x19, 0x06, 0xC9, 0x20, 0x34, 0x70, 0xC6, 0x01, 0x3F, 0x72, 0x30, 0xA5, 0x82,
0xC5, 0x04, 0x28, 0xCE, 0x40, 0x4B, 0x39, 0xDD, 0x2E, 0x41, 0x8B, 0x69, 0x34, 0x2F, 0x2F, 0x2F,
0x00, 0x34, 0x41, 0x8F, 0x5F, 0x20, 0x98, 0x30, 0x4E, 0x29, 0x20, 0x1B, 0x20, 0xD5, 0x35, 0x33,
0x1F, 0x1B, 0x23, 0x2E, 0x20, 0x84, 0x50, 0x2A, 0x1D, 0x72, 0x6D, 0xA7, 0xFE, 0x27, 0x90, 0xA8,
0xB2, 0x1C, 0xAC, 0xA5, 0xA5, 0xA5, 0xA5, 0xA7, 0xA7, 0xAB, 0x00, 0x3D, 0x1F, 0x22, 0x54, 0x40,
0xAC, 0x03, 0x67, 0x91, 0x45, 0x21, 0x58, 0x2E, 0x50, 0x41, 0xB0, 0xC7, 0x84, 0x1E, 0x2E, 0x63,
0x7C, 0xA0, 0x07, 0x8F, 0x75, 0x73, 0x73, 0x73, 0x72, 0x70, 0x3E, 0x00, 0x27, 0x1B, 0x23, 0x40,
0x6F, 0x10, 0x20, 0x09, 0x05, 0x65, 0x60, 0xC5, 0x14, 0x31, 0x1E, 0xB6, 0x10, 0x41, 0x20, 0x19,
0x1B, 0x95, 0x91, 0x99, 0xF9, 0x03, 0xEA, 0x72, 0x22, 0x2F, 0x43, 0x7C, 0x61, 0x37, 0x03, 0x32,
0x33, 0x33, 0x31, 0x2D, 0x24, 0x1E, 0xC9, 0x40, 0x80, 0x57, 0x34, 0x25, 0x2B, 0x41, 0x6D, 0x41,
0x00, 0x94, 0x40, 0x3D, 0x28, 0x27, 0x2E, 0x49, 0x73, 0x85, 0x20, 0x64, 0x71, 0xC0, 0x29, 0x27,
0xCC, 0x60, 0xA0, 0x25, 0x29, 0x2D, 0x28, 0x20, 0x1E, 0x07, 0x1E, 0x1F, 0x1E, 0x16, 0x04, 0x85,
0x00, 0x71, 0x10, 0x00, 0x6D, 0x58, 0x53, 0x44, 0x4A, 0x5D, 0x7A, 0x4A, 0x00, 0xA0, 0x58, 0x20,
0x48, 0x45, 0x4B, 0x63, 0x7C, 0x85, 0x20, 0x38, 0x58, 0x95, 0x31, 0xE0, 0x29, 0x83, 0x64, 0x70,
0x53, 0x23, 0x78, 0x03, 0x28, 0x12, 0x16, 0x21, 0x56, 0x40, 0x70, 0x10, 0x00, 0x07, 0x00, 0xE1,
0xE3, 0xE3, 0xF8, 0x0C, 0xFF, 0xFF, 0xEB, 0xE3, 0xCC, 0x15, 0xE3, 0x41, 0x10, 0x2A, 0x50, 0x65,
0x51, 0x0D, 0x11, 0x71, 0x03, 0x29, 0xB4, 0x1E, 0x2C, 0x4E, 0x81, 0x0F, 0x26, 0x2D, 0x5D, 0x96,
0x8E, 0x3B, 0x1F, 0x1B, 0x00, 0x22, 0x40, 0x6F, 0x01, 0x10, 0x3D, 0xF0, 0x4F, 0x29, 0x54, 0x30,
0x98, 0x1A, 0x85, 0x20, 0xDA, 0x95, 0x11, 0x19, 0x82, 0x70, 0x1E, 0x26, 0x2A, 0x4B, 0xAE, 0x78,
0x2F, 0x4C, 0xAF, 0x84, 0x88, 0x00, 0xA3, 0x28, 0x1C, 0x21, 0x3E, 0x6A, 0x01, 0x10, 0x3D, 0xF0,
0xC0, 0x4B, 0x1C, 0x51, 0x1C, 0x98, 0x00, 0xB5, 0x93, 0x1A, 0xFA, 0x23, 0x30, 0x5A, 0x7D, 0x85,
0x38, 0x37, 0x7C, 0x8D, 0x49, 0x4E, 0x00, 0x98, 0x54, 0x1E, 0x1F, 0x36, 0xD5, 0x55, 0x4D, 0xF5,
0x19, 0x60, 0xA5, 0x62, 0xD9, 0x11, 0x58, 0xA7, 0x20, 0x36, 0x89, 0x68, 0x2F, 0x07, 0x3F, 0x9F,
0x5F, 0x2F, 0x40, 0x8B, 0x62, 0x20, 0x00, 0x20, 0x2B, 0x43, 0x5D, 0x6B, 0x04, 0x00, 0xDA, 0x35,
0xD0, 0x15, 0xE0, 0x86, 0x06, 0x71, 0x6E, 0xD5, 0x05, 0xC5, 0x84, 0x33, 0x48, 0xDC, 0x19, 0xF9,
0x53, 0x1A, 0xB2, 0x54, 0x7C, 0x79, 0x3C, 0x56, 0xB0, 0x05, 0x37, 0x2B, 0x43, 0x97, 0x4D, 0x21,
0x1C, 0x21, 0x00, 0x2A, 0x36, 0x3C, 0x09, 0x30, 0x41, 0x3F, 0xD2, 0x75, 0x3A, 0x48, 0x31, 0x85,
0xB0, 0x95, 0x01, 0x00, 0x97, 0x1C, 0x1E, 0x2B, 0x50, 0x0E, 0xAB, 0x8E, 0xA1, 0x8A, 0x31, 0x43,
0x86, 0xA4, 0x00, 0x2E, 0x1D, 0xE7, 0x04, 0x27, 0x29, 0x2D, 0x02, 0x03, 0x10, 0x2A, 0x64, 0x00,
0x00, 0x2A, 0x28, 0x10, 0x12, 0x28, 0x28, 0x22, 0x9D, 0x42, 0x89, 0xE9, 0x72, 0x1C, 0x86, 0xA6,
0x23, 0x36, 0x55, 0x86, 0x7D, 0x05, 0x37, 0x2D, 0x5B, 0x97, 0x47, 0x6D, 0x01, 0x21, 0x29, 0x20,
0x35, 0x3A, 0x3C, 0x3D, 0x3A, 0x3B, 0x3C, 0x3D, 0x00, 0x3C, 0x3B, 0x03, 0x10, 0x3C, 0x3C, 0x3C,
0x3C, 0x3B, 0x04, 0x3B, 0x37, 0x2E, 0x4D, 0x95, 0x34, 0x45, 0xC5, 0x04, 0x0E, 0x31, 0xC8, 0x43,
0x50, 0x1E, 0x22, 0x2E, 0x33, 0x2E, 0x24, 0x22, 0x01, 0x2E, 0x31, 0x27, 0x1E, 0x1B, 0x20, 0x2B,
0x40, 0x00, 0xB7, 0xBB, 0x02, 0x20, 0x03, 0x30, 0x00, 0x00, 0xBE, 0xBE, 0xBE, 0x1C, 0xBD, 0xBA,
0xB3, 0x31, 0x22, 0xC9, 0x80, 0x41, 0x10, 0x1C, 0x60, 0x1C, 0xFA, 0xB5, 0x1F, 0x21, 0x1E, 0x10,
0x15, 0xAE, 0x13, 0x34, 0x62, 0x57, 0x01, 0x10, 0x3D, 0xF0, 0x3E, 0x25, 0x1B, 0x1C, 0x51, 0x81,
0x86, 0x39, 0x29, 0x95, 0xB1, 0x21, 0x2B, 0x35, 0x36, 0x36, 0x04, 0x36, 0x35, 0x34, 0x31, 0x29,
0x20, 0x6A, 0x02, 0x65, 0x40, 0x01, 0x10, 0x3D, 0xF0, 0x48, 0x27, 0x09, 0x44, 0x1D, 0x52, 0x1E,
0xB2, 0x2B, 0x73, 0x88, 0xBA, 0xBB, 0xBA, 0xBC, 0xBA, 0xBA, 0xBC, 0x00, 0xA1, 0x24, 0x1B, 0x22,
0x38, 0x5F, 0x01, 0x10, 0x29, 0xF3, 0xC0, 0x43, 0x0C, 0x20, 0xD9, 0x71, 0x27, 0x3D, 0xA1, 0x1D,
0x29, 0x3D, 0x16, 0x4B, 0x51, 0x51, 0x51, 0x53, 0x5A, 0x7B, 0x92, 0x00, 0x2B, 0x1B, 0x20, 0x30,
0x49, 0x96, 0x9E, 0xA2, 0x00, 0xA2, 0xA2, 0xA2, 0xA2, 0xA5, 0xA5, 0xEA, 0xFF, 0x00, 0xFF, 0xBE,
0xA4, 0xA3, 0xA2, 0xA2, 0xA1, 0xA3, 0x00, 0xA0, 0x9A, 0x8A, 0x37, 0x24, 0xF9, 0x72, 0x35, 0x46,
0x20, 0xDB, 0x3B, 0x29, 0x1B, 0x1C, 0xF8, 0x80, 0x1D, 0x1F, 0x20, 0x22, 0x27, 0x27, 0x27, 0x28,
0x2A, 0x34, 0x4A, 0x00, 0x97, 0x4A, 0x1E, 0x1E, 0x24, 0x31, 0x40, 0x49, 0x00, 0x0B, 0x00, 0x4D,
0x51, 0x63, 0x7C, 0x41, 0x00, 0xA2, 0x60, 0x21, 0x50, 0x4C, 0x4D, 0x4D, 0x4D, 0x4C, 0x43, 0x37,
0x00, 0x28, 0x82, 0x70, 0x21, 0x33, 0x46, 0xA5, 0x02, 0x7D, 0xC1, 0xE9, 0x42, 0xE2, 0x3E, 0x8A,
0x62, 0x1F, 0x1B, 0x1D, 0x21, 0x26, 0x00, 0x27, 0x28, 0x29, 0x29, 0x2A, 0x2F, 0x45, 0x6E, 0x00,
0x41, 0x00, 0x96, 0x40, 0x2D, 0x2A, 0x29, 0x2A, 0x29, 0x01, 0x28, 0x20, 0x04, 0x1D, 0x41, 0xB0,
0x27, 0x1F, 0x14, 0x3D, 0x81, 0x24, 0x6A, 0x26, 0x29, 0x27, 0x29, 0x2B, 0x33, 0x4A, 0xA5, 0x00,
0x4D, 0x1E, 0x16, 0x24, 0x1E, 0x1E, 0x1C, 0x1E, 0x23, 0x04, 0x3A, 0x69, 0x41, 0x10, 0x35, 0x20,
0x1D, 0x1D, 0x1D, 0x04, 0x1D, 0x1D, 0xF1, 0x10, 0x2D, 0x83, 0xC9, 0xE0, 0x1D, 0x24, 0x60, 0x1C,
0x86, 0x87, 0x87, 0x88, 0x89, 0x98, 0xAF, 0x8A, 0x00, 0x2E, 0xF4, 0x73, 0x20, 0x3A, 0xC9, 0x40,
0x1C, 0x5F, 0xE3, 0x22, 0x52, 0x41, 0x10, 0x27, 0x2D, 0xA0, 0x1E, 0x24, 0x4E, 0x67, 0x6A, 0x05,
0x6A, 0x6B, 0x6D, 0x6F, 0x59, 0x34, 0x22, 0xD1, 0x83, 0x80, 0x39, 0x85, 0x20, 0x32, 0x20, 0x18,
0x60, 0x1D, 0xA2, 0x3B, 0x28, 0x32, 0x0B, 0xA3, 0x1C, 0x20, 0x27, 0x2D, 0x2F, 0x2E, 0x2E, 0x01,
0x31, 0x2E, 0x28, 0x21, 0x42, 0x83, 0x21, 0x3A, 0x41, 0x10, 0x90, 0x91, 0x33, 0x20, 0xA7, 0x83,
0x19, 0x85, 0x40, 0x41, 0x60, 0x19, 0x82, 0xE8, 0x20, 0x1F, 0x20, 0x1E, 0x1F, 0x21, 0x1F, 0x1C,
0x00, 0x45, 0x93, 0x20, 0x38, 0x66, 0x85, 0x00, 0x90, 0x33, 0x26, 0x62, 0x91, 0xD9, 0x80, 0x95,
0x01, 0x3A, 0x85, 0x20, 0x1C, 0x81, 0x41, 0x20, 0x27, 0x2B, 0x32, 0x56, 0x35, 0x1D, 0x1D, 0x24,
0x49, 0x4A, 0x00, 0x28, 0x20, 0x1B, 0x1D, 0x12, 0x23, 0x26, 0x26, 0x26, 0x08, 0x26, 0x27, 0x2A,
0x3F, 0x6C, 0xE2, 0xFF, 0xFF, 0x00, 0x94, 0x3E, 0x28, 0x25, 0x26, 0x27, 0x27, 0x26, 0x00, 0x24,
0x21, 0x1E, 0xE8, 0x10, 0x1C, 0xD9, 0x71, 0x1D, 0x22, 0x1C, 0x68, 0x3A, 0x32, 0x1E, 0x2D, 0x61,
0xB1, 0xA8, 0x51, 0x1E, 0x01, 0x1D, 0x2B, 0x77, 0xAF, 0xA3, 0x3D, 0x20, 0x1B, 0x00, 0x1D, 0x22,
0x2E, 0x3A, 0x41, 0x45, 0x45, 0x45, 0x00, 0x46, 0x48, 0x5C, 0x79, 0xE3, 0xFF, 0xFF, 0xA1, 0x00,
0x5A, 0x49, 0x45, 0x44, 0x45, 0x45, 0x43, 0x3E, 0x00, 0x33, 0x26, 0x20, 0x1B, 0x1C, 0x0D, 0x61,
0xC9, 0x00, 0x41, 0x80, 0xE0, 0x1C, 0x26, 0x4D, 0xB1, 0x71, 0x3D, 0x27, 0x1C, 0x00, 0x1D, 0x26,
0x39, 0x4E, 0x81, 0x9B, 0x27, 0x1B, 0x00, 0x1F, 0x2E, 0x47, 0xDE, 0xE0, 0xE2, 0xE2, 0x07, 0x10,
0x80, 0xE3, 0xF7, 0xFF, 0xFF, 0xEA, 0xE3, 0xE2, 0xE2, 0x00, 0xE2, 0xE3, 0xE2, 0xE1, 0xE0, 0xDD,
0x34, 0x21, 0x00, 0x41, 0x90, 0xDA, 0x41, 0x90, 0x20, 0x2F, 0x7E, 0x8B, 0x38, 0x05, 0x25, 0x1E,
0x49, 0x12, 0x32, 0x4B, 0x9D, 0x3D, 0x1D, 0x04, 0x1F, 0x37, 0x5D, 0x03, 0x30, 0x85, 0xF0, 0x1E,
0x72, 0x35, 0x85, 0x00, 0xB8, 0x28, 0xC9, 0x70, 0x22, 0x37, 0x8B, 0x68, 0x27, 0xDE, 0x31, 0x82,
0x26, 0x3F, 0x8A, 0x61, 0x21, 0x21, 0x3B, 0x66, 0x00, 0x01, 0x10, 0x3D, 0xF0, 0x47, 0x28, 0x92,
0x61, 0xC9, 0x00, 0xDA, 0x3B, 0x33, 0x27, 0x1C, 0xF3, 0x61, 0x21, 0x38, 0x8B, 0x71, 0x25, 0x04,
0x76, 0x30, 0x24, 0x3C, 0x91, 0x62, 0x21, 0x1F, 0x35, 0x01, 0x5B, 0x07, 0x70, 0x03, 0x30, 0x00,
0x00, 0xFF, 0xFF, 0xFF, 0x41, 0x0E, 0x25, 0xD9, 0x60, 0x21, 0x34, 0x47, 0xDB, 0x39, 0x27, 0x02,
0xA6, 0x71, 0x1F, 0x31, 0x65, 0xA4, 0x32, 0x20, 0x55, 0x11, 0x81, 0x20, 0x2E, 0x55, 0xAA, 0x34,
0x1E, 0x1E, 0x2C, 0x00, 0x42, 0x5C, 0x6A, 0x01, 0x00, 0x71, 0x6F, 0x03, 0x10, 0x70, 0x48, 0x00,
0x00, 0x70, 0x70, 0x6F, 0x6F, 0x6D, 0x63, 0x4C, 0x01, 0x32, 0xAC, 0x20, 0x1C, 0x41, 0x30, 0x48,
0xDB, 0x3A, 0x26, 0x0A, 0x32, 0x50, 0xFD, 0x10, 0x42, 0x92, 0x9D, 0x52, 0x33, 0x2F, 0x03, 0x2F,
0x32, 0x3A, 0x6C, 0xAB, 0x72, 0x29, 0x1D, 0x00, 0x1B, 0x21, 0x2B, 0x36, 0x3D, 0x40, 0x3F, 0x05,
0x40, 0x80, 0x41, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x3F, 0x39, 0x02, 0x30, 0x24, 0x40, 0x70,
0x21, 0x35, 0x47, 0xDC, 0x3A, 0x04, 0x29, 0x65, 0x80, 0x20, 0x2D, 0x46, 0x81, 0xB0, 0xB0, 0x02,
0xA4, 0xA5, 0xA6, 0xB6, 0xA6, 0x6B, 0x32, 0x20, 0x00, 0x1B, 0x1B, 0x1D, 0x20, 0x20, 0x21, 0x22,
0x0B, 0x10, 0x80, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x23, 0x22, 0x00, 0x21, 0x23, 0x23, 0x21,
0x22, 0x21, 0x1E, 0x1E, 0x00, 0x25, 0x70, 0x20, 0x32, 0x45, 0xDA, 0x37, 0x27, 0x62, 0x30, 0x81,
0x8A, 0x30, 0x1F, 0x2B, 0x3C, 0x4A, 0x59, 0x71, 0x71, 0x01, 0x70, 0x4B, 0x3E, 0x2E, 0x21, 0x0A,
0x90, 0x1A, 0x04, 0x40, 0xA0, 0x6E, 0xF0, 0x21, 0x2E, 0x3B, 0xDC, 0x32, 0x24, 0x1B, 0x40, 0x81,
0x1A, 0x0C, 0x20, 0x1E, 0x23, 0x27, 0x2D, 0x32, 0x30, 0x02, 0x2E, 0x28, 0x24, 0x1E, 0x55, 0xC0,
0x19, 0x7A, 0x20, 0x19, 0x50, 0x45, 0xA0, 0x1C, 0x37, 0x00, 0x1E, 0x27, 0x2D, 0x30, 0x29, 0x05,
0x1F, 0x12, 0xC0, 0x73, 0x00, 0x1E, 0x1F, 0x2C, 0x80, 0x22, 0xF0, 0x53, 0xB0, 0xE6, 0x1F, 0x24,
0x24, 0x21, 0x1D, 0x1C, 0xF0, 0x1C, 0x1B, 0x80, 0xA0, 0x19, 0x02, 0x20, 0x1D, 0xF0, 0x0A, 0x60,
0x1C, 0x1C, 0x1C, 0x1D, 0x0E, 0x1C, 0x0A, 0xA0, 0x1B, 0x03, 0x30, 0x00, 0x00, 0x1B, 0x1B, 0x1B,
0x1A, 0xFF, 0xFF, 0xFF, 0x30, 0x1A, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x18, 0x00, 0x00
};
#endif

85
ipl/tui.c → bootloader/gfx/tui.c Executable file → Normal file
View File

@@ -1,25 +1,27 @@
/*
* 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/>.
*/
* 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 "tui.h"
#include "btn.h"
#include "max17050.h"
#include "config.h"
#include "util.h"
#include "../utils/btn.h"
#include "../config/config.h"
#include "../power/max17050.h"
#include "../utils/util.h"
#include "../config/config.h"
#include "di.h"
#ifdef MENU_LOGO_ENABLE
extern u8 *Kc_MENU_LOGO;
@@ -31,8 +33,10 @@ extern u8 *Kc_MENU_LOGO;
extern hekate_config h_cfg;
void tui_sbar(gfx_con_t *con, int force_update)
void tui_sbar(gfx_con_t *con, bool force_update)
{
u32 cx, cy;
u32 timePassed = get_tmr_s() - h_cfg.sbar_time_keeping;
if (!force_update)
if (timePassed < 5)
@@ -45,7 +49,7 @@ void tui_sbar(gfx_con_t *con, int force_update)
u32 battPercent = 0;
int battVoltCurr = 0;
gfx_con_getpos(con, &con->savedx, &con->savedy);
gfx_con_getpos(con, &cx, &cy);
gfx_con_setpos(con, 0, 1260);
max17050_get_property(MAX17050_RepSOC, (int *)&battPercent);
@@ -58,13 +62,13 @@ void tui_sbar(gfx_con_t *con, int force_update)
max17050_get_property(MAX17050_AvgCurrent, &battVoltCurr);
if (battVoltCurr >= 0)
gfx_printf(con, " %k+%d mA %k%K\n",
0xFF008000, battVoltCurr / 1000, 0xFFCCCCCC, 0xFF1B1B1B);
gfx_printf(con, " %k+%d mA%k%K\n",
0xFF008800, battVoltCurr / 1000, 0xFFCCCCCC, 0xFF1B1B1B);
else
gfx_printf(con, " %k-%d mA %k%K\n",
0xFF800000, (~battVoltCurr) / 1000, 0xFFCCCCCC, 0xFF1B1B1B);
gfx_printf(con, " %k-%d mA%k%K\n",
0xFF880000, (~battVoltCurr) / 1000, 0xFFCCCCCC, 0xFF1B1B1B);
con->fntsz = prevFontSize;
gfx_con_setpos(con, con->savedx, con->savedy);
gfx_con_setpos(con, cx, cy);
}
void tui_pbar(gfx_con_t *con, int x, int y, u32 val, u32 fgcol, u32 bgcol)
@@ -90,7 +94,7 @@ void tui_pbar(gfx_con_t *con, int x, int y, u32 val, u32 fgcol, u32 bgcol)
gfx_con_setpos(con, cx, cy);
// Update status bar.
tui_sbar(con, 0);
tui_sbar(con, false);
}
void *tui_do_menu(gfx_con_t *con, menu_t *menu)
@@ -98,14 +102,14 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
int idx = 0, prev_idx = 0, cnt = 0x7FFFFFFF;
gfx_clear_partial_grey(con->gfx_ctxt, 0x1B, 0, 1256);
tui_sbar(con, 1);
tui_sbar(con, true);
#ifdef MENU_LOGO_ENABLE
gfx_set_rect_rgb(con->gfx_ctxt, Kc_MENU_LOGO,
X_MENU_LOGO, Y_MENU_LOGO, X_POS_MENU_LOGO, Y_POS_MENU_LOGO);
#endif //MENU_LOGO_ENABLE
while (1)
while (true)
{
gfx_con_setcol(con, 0xFFCCCCCC, 1, 0xFF1B1B1B);
gfx_con_setpos(con, menu->x, menu->y);
@@ -155,21 +159,35 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
gfx_putc(con, '\n');
// Print help and battery status.
gfx_con_getpos(con, &con->savedx, &con->savedy);
gfx_con_setpos(con, 0, 1127);
if (h_cfg.errors)
{
gfx_printf(con, "%k Warning: %k", 0xFF800000, 0xFF555555);
if (h_cfg.errors & ERR_LIBSYS_LP0)
gfx_printf(con, "Sleep mode library is missing!\n");
}
gfx_con_setpos(con, 0, 1191);
gfx_printf(con, "%k VOL: Move up/down\n PWR: Select option%k", 0xFF555555, 0xFFCCCCCC);
display_backlight_brightness(h_cfg.backlight, 1000);
// Wait for user command.
u32 btn = btn_wait();
if (btn & BTN_VOL_DOWN && idx < (cnt - 1))
idx++;
else if (btn & BTN_VOL_DOWN && idx == (cnt - 1))
{
idx = 0;
prev_idx = -1;
}
if (btn & BTN_VOL_UP && idx > 0)
idx--;
else if (btn & BTN_VOL_UP && idx == 0)
{
idx = cnt - 1;
prev_idx = cnt;
}
if (btn & BTN_POWER)
{
ment_t *ent = &menu->ents[idx];
@@ -181,12 +199,15 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
case MENT_MENU:
return tui_do_menu(con, ent->menu);
break;
case MENT_CHOICE:
case MENT_DATA:
return ent->data;
break;
case MENT_BACK:
return NULL;
break;
case MENT_HDLR_RE:
ent->handler(ent->data);
return NULL;
default:
break;
}
@@ -197,7 +218,7 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
X_MENU_LOGO, Y_MENU_LOGO, X_POS_MENU_LOGO, Y_POS_MENU_LOGO);
#endif //MENU_LOGO_ENABLE
}
tui_sbar(con, 0);
tui_sbar(con, false);
}
return NULL;

7
ipl/tui.h → bootloader/gfx/tui.h Executable file → Normal file
View File

@@ -18,16 +18,17 @@
#ifndef _TUI_H_
#define _TUI_H_
#include "types.h"
#include "../utils/types.h"
#include "gfx.h"
#define MENT_END 0
#define MENT_HANDLER 1
#define MENT_MENU 2
#define MENT_CHOICE 3
#define MENT_DATA 3
#define MENT_BACK 4
#define MENT_CAPTION 5
#define MENT_CHGLINE 6
#define MENT_HDLR_RE 7
typedef struct _ment_t
{
@@ -58,7 +59,7 @@ typedef struct _menu_t
#define MDEF_CAPTION(caption, color) { MENT_CAPTION, caption, color }
#define MDEF_CHGLINE() {MENT_CHGLINE}
void tui_sbar(gfx_con_t *con, int force_update);
void tui_sbar(gfx_con_t *con, bool force_update);
void tui_pbar(gfx_con_t *con, int x, int y, u32 val, u32 fgcol, u32 bgcol);
void *tui_do_menu(gfx_con_t *con, menu_t *menu);

421
ipl/hos.c → bootloader/hos/hos.c Executable file → Normal file
View File

@@ -1,51 +1,55 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018 Ced2911
* 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/>.
*/
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018 Ced2911
* Copyright (C) 2018 CTCaer
* Copyright (c) 2018 balika011
*
* 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 "hos.h"
#include "sdmmc.h"
#include "nx_emmc.h"
#include "t210.h"
#include "se.h"
#include "se_t210.h"
#include "pmc.h"
#include "cluster.h"
#include "heap.h"
#include "tsec.h"
#include "pkg2.h"
#include "nx_emmc.h"
#include "util.h"
#include "../storage/sdmmc.h"
#include "../storage/nx_emmc.h"
#include "../soc/t210.h"
#include "../sec/se.h"
#include "../sec/se_t210.h"
#include "../soc/pmc.h"
#include "../soc/cluster.h"
#include "../mem/heap.h"
#include "../sec/tsec.h"
#include "../utils/util.h"
#include "pkg1.h"
#include "pkg2.h"
#include "ff.h"
#include "di.h"
#include "config.h"
#include "../libs/fatfs/ff.h"
#include "../gfx/di.h"
#include "../config/config.h"
#include "../mem/mc.h"
#include "../soc/fuse.h"
#include "../utils/dirlist.h"
#include "gfx.h"
#include "../gfx/gfx.h"
extern gfx_ctxt_t gfx_ctxt;
extern gfx_con_t gfx_con;
extern hekate_config h_cfg;
extern void sd_unmount();
//#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
#define DPRINTF(...)
extern hekate_config h_cfg;
typedef struct _launch_ctxt_t
{
void *keyblob;
@@ -65,10 +69,11 @@ typedef struct _launch_ctxt_t
void *kernel;
u32 kernel_size;
link_t kip1_list;
char* kip1_patches;
int svcperm;
int debugmode;
int atmosphere;
bool svcperm;
bool debugmode;
bool atmosphere;
} launch_ctxt_t;
typedef struct _merge_kip_t
@@ -82,9 +87,10 @@ typedef struct _merge_kip_t
#define KB_FIRMWARE_VERSION_301 2
#define KB_FIRMWARE_VERSION_400 3
#define KB_FIRMWARE_VERSION_500 4
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_500
#define KB_FIRMWARE_VERSION_600 5
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_600
// Exosphère magic "XBC0"
// Exosphère magic "XBC0".
#define MAGIC_EXOSPHERE 0x30434258
static const u8 keyblob_keyseeds[][0x10] = {
@@ -92,7 +98,8 @@ static const u8 keyblob_keyseeds[][0x10] = {
{ 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, //3.0.0
{ 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, //3.0.1
{ 0x2D, 0x1F, 0x48, 0x80, 0xED, 0xEC, 0xED, 0x3E, 0x3C, 0xF2, 0x48, 0xB5, 0x65, 0x7D, 0xF7, 0xBE }, //4.0.0
{ 0xBB, 0x5A, 0x01, 0xF9, 0x88, 0xAF, 0xF5, 0xFC, 0x6C, 0xFF, 0x07, 0x9E, 0x13, 0x3C, 0x39, 0x80 } //5.0.0
{ 0xBB, 0x5A, 0x01, 0xF9, 0x88, 0xAF, 0xF5, 0xFC, 0x6C, 0xFF, 0x07, 0x9E, 0x13, 0x3C, 0x39, 0x80 }, //5.0.0
{ 0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0 } //6.0.0
};
static const u8 cmac_keyseed[0x10] =
@@ -122,12 +129,14 @@ static void _se_lock()
for (u32 i = 0; i < 2; i++)
se_rsa_acc_ctrl(i, 1);
SE(0x4) = 0; //Make this reg secure only.
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = 0; //Make all key access regs secure only.
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = 0; //Make all rsa access regs secure only.
SE(SE_SECURITY_0) &= 0xFFFFFFFB; //Make access lock regs secure only.
SE(0x4) = 0; // Make this reg secure only.
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = 0; // Make all key access regs secure only.
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = 0; // Make all RSA access regs secure only.
SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs secure only.
memset((void *)IPATCH_BASE, 0, 13);
SB(SB_CSR) = 0x10; // Protected IROM enable.
//This is useful for documenting the bits in the SE config registers, so we can keep it around.
// This is useful for documenting the bits in the SE config registers, so we can keep it around.
/*gfx_printf(&gfx_con, "SE(SE_SECURITY_0) = %08X\n", SE(SE_SECURITY_0));
gfx_printf(&gfx_con, "SE(0x4) = %08X\n", SE(0x4));
gfx_printf(&gfx_con, "SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = %08X\n", SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET));
@@ -141,6 +150,36 @@ static void _se_lock()
gfx_hexdump(&gfx_con, SE_BASE, (void *)SE_BASE, 0x400);*/
}
void _pmc_scratch_lock(u32 kb)
{
switch (kb)
{
case KB_FIRMWARE_VERSION_100_200:
case KB_FIRMWARE_VERSION_300:
case KB_FIRMWARE_VERSION_301:
PMC(APBDEV_PMC_SEC_DISABLE) = 0x7FFFF3;
PMC(APBDEV_PMC_SEC_DISABLE2) = 0xFFFFFFFF;
PMC(APBDEV_PMC_SEC_DISABLE3) = 0xFFAFFFFF;
PMC(APBDEV_PMC_SEC_DISABLE4) = 0xFFFFFFFF;
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF;
PMC(APBDEV_PMC_SEC_DISABLE6) = 0xFFFFFFFF;
PMC(APBDEV_PMC_SEC_DISABLE7) = 0xFFFFFFFF;
PMC(APBDEV_PMC_SEC_DISABLE8) = 0xFFAAFFFF;
break;
case KB_FIRMWARE_VERSION_400:
case KB_FIRMWARE_VERSION_500:
case KB_FIRMWARE_VERSION_600:
default:
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF;
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF;
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF;
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F;
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF;
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF;
break;
}
}
int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
{
u8 tmp[0x10];
@@ -151,19 +190,19 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
se_key_acc_ctrl(13, 0x15);
se_key_acc_ctrl(14, 0x15);
//Get TSEC key.
// Get TSEC key.
if (tsec_query(tmp, 1, tsec_fw) < 0)
return 0;
se_aes_key_set(13, tmp, 0x10);
//Derive keyblob keys from TSEC+SBK.
// Derive keyblob keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp);
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]);
se_aes_unwrap_key(13, 14, tmp);
//Clear SBK.
// Clear SBK.
se_aes_key_clear(14);
//TODO: verify keyblob CMAC.
@@ -175,9 +214,9 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed);
se_aes_unwrap_key(11, 13, cmac_keyseed);
//Decrypt keyblob and set keyslots.
// Decrypt keyblob and set keyslots.
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); //Package1 key.
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); // Package1 key.
se_aes_key_set(12, keyblob + 0x20, 0x10);
se_aes_key_set(13, keyblob + 0x20, 0x10);
@@ -185,50 +224,35 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
switch (kb)
{
case KB_FIRMWARE_VERSION_100_200:
case KB_FIRMWARE_VERSION_300:
case KB_FIRMWARE_VERSION_301:
se_aes_unwrap_key(13, 15, console_keyseed);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
case KB_FIRMWARE_VERSION_400:
se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
case KB_FIRMWARE_VERSION_500:
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
case KB_FIRMWARE_VERSION_100_200:
case KB_FIRMWARE_VERSION_300:
case KB_FIRMWARE_VERSION_301:
se_aes_unwrap_key(13, 15, console_keyseed);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
case KB_FIRMWARE_VERSION_400:
se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
case KB_FIRMWARE_VERSION_500:
case KB_FIRMWARE_VERSION_600:
default:
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
}
//Package2 key.
// Package2 key.
se_key_acc_ctrl(8, 0x15);
se_aes_unwrap_key(8, 12, key8_keyseed);
return 1;
}
static void _copy_bootconfig()
{
sdmmc_storage_t storage;
sdmmc_t sdmmc;
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
//Read BCT.
u8 *buf = (u8 *)0x4003D000;
sdmmc_storage_set_mmc_partition(&storage, 1);
sdmmc_storage_read(&storage, 0, 0x3000 / NX_EMMC_BLOCKSIZE, buf);
gfx_printf(&gfx_con, "Copied BCT to 0x4003D000\n");
sdmmc_storage_end(&storage);
}
static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
{
int res = 0;
@@ -237,19 +261,19 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
//Read package1.
// Read package1.
ctxt->pkg1 = (u8 *)malloc(0x40000);
sdmmc_storage_set_mmc_partition(&storage, 1);
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, ctxt->pkg1);
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1);
if (!ctxt->pkg1_id)
{
gfx_printf(&gfx_con, "%kCould not identify package1,\nVersion (= '%s').%k\n", 0xFFFF0000, (char *)ctxt->pkg1 + 0x10, 0xFFCCCCCC);
gfx_printf(&gfx_con, "%kUnknown package1,\nVersion (= '%s').%k\n", 0xFFFF0000, (char *)ctxt->pkg1 + 0x10, 0xFFCCCCCC);
goto out;
}
gfx_printf(&gfx_con, "Identified package1 ('%s'),\nKeyblob version %d\n\n", (char *)(ctxt->pkg1 + 0x10), ctxt->pkg1_id->kb);
//Read the correct keyblob.
// Read the correct keyblob.
ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
@@ -260,46 +284,49 @@ out:;
return res;
}
static int _read_emmc_pkg2(launch_ctxt_t *ctxt)
static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt)
{
int res = 0;
u8 *bctBuf = NULL;
sdmmc_storage_t storage;
sdmmc_t sdmmc;
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
return NULL;
sdmmc_storage_set_mmc_partition(&storage, 0);
//Parse eMMC GPT.
// Parse eMMC GPT.
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage);
DPRINTF("Parsed GPT\n");
//Find package2 partition.
// Find package2 partition.
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
if (!pkg2_part)
goto out;
//Read in package2 header and get package2 real size.
// Read in package2 header and get package2 real size.
//TODO: implement memalign for DMA buffers.
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
u32 *hdr = (u32 *)(tmp + 0x100);
static const u32 BCT_SIZE = 0x4000;
bctBuf = (u8 *)malloc(BCT_SIZE);
nx_emmc_part_read(&storage, pkg2_part, BCT_SIZE / NX_EMMC_BLOCKSIZE, 1, bctBuf);
u32 *hdr = (u32 *)(bctBuf + 0x100);
u32 pkg2_size = hdr[0] ^ hdr[2] ^ hdr[3];
free(tmp);
DPRINTF("pkg2 size on emmc is %08X\n", pkg2_size);
//Read in package2.
// Read in Boot Config.
memset(bctBuf, 0, BCT_SIZE);
nx_emmc_part_read(&storage, pkg2_part, 0, BCT_SIZE / NX_EMMC_BLOCKSIZE, bctBuf);
// Read in package2.
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
DPRINTF("pkg2 size aligned is %08X\n", pkg2_size_aligned);
ctxt->pkg2 = malloc(pkg2_size_aligned);
ctxt->pkg2_size = pkg2_size;
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
nx_emmc_part_read(&storage, pkg2_part, BCT_SIZE / NX_EMMC_BLOCKSIZE,
pkg2_size_aligned / NX_EMMC_BLOCKSIZE, ctxt->pkg2);
res = 1;
out:;
nx_emmc_gpt_free(&gpt);
sdmmc_storage_end(&storage);
return res;
return bctBuf;
}
static int _config_warmboot(launch_ctxt_t *ctxt, const char *value)
@@ -341,14 +368,61 @@ static int _config_kernel(launch_ctxt_t *ctxt, const char *value)
static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
{
FIL fp;
if (f_open(&fp, value, FA_READ) != FR_OK)
return 0;
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
mkip1->kip1 = malloc(f_size(&fp));
f_read(&fp, mkip1->kip1, f_size(&fp), NULL);
DPRINTF("Loaded kip1 from SD (size %08X)\n", f_size(&fp));
f_close(&fp);
list_append(&ctxt->kip1_list, &mkip1->link);
if (!memcmp(value + strlen(value) - 1, "*", 1))
{
char *dir = (char *)malloc(256);
memcpy(dir, value, strlen(value) + 1);
u32 dirlen = 0;
dir[strlen(dir) - 2] = 0;
char *filelist = dirlist(dir, "*.kip*");
memcpy(dir + strlen(dir), "/", 2);
dirlen = strlen(dir);
u32 i = 0;
if (filelist)
{
while (true)
{
if (!filelist[i * 256])
break;
memcpy(dir + dirlen, &filelist[i * 256], strlen(&filelist[i * 256]) + 1);
if (f_open(&fp, dir, FA_READ))
{
free(dir);
free(filelist);
return 0;
}
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
mkip1->kip1 = malloc(f_size(&fp));
f_read(&fp, mkip1->kip1, f_size(&fp), NULL);
DPRINTF("Loaded kip1 from SD (size %08X)\n", f_size(&fp));
f_close(&fp);
list_append(&ctxt->kip1_list, &mkip1->link);
i++;
}
}
free(dir);
free(filelist);
}
else
{
if (f_open(&fp, value, FA_READ))
return 0;
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
mkip1->kip1 = malloc(f_size(&fp));
f_read(&fp, mkip1->kip1, f_size(&fp), NULL);
DPRINTF("Loaded kip1 from SD (size %08X)\n", f_size(&fp));
f_close(&fp);
list_append(&ctxt->kip1_list, &mkip1->link);
}
return 1;
}
@@ -357,7 +431,7 @@ static int _config_svcperm(launch_ctxt_t *ctxt, const char *value)
if (*value == '1')
{
DPRINTF("Disabled SVC verification\n");
ctxt->svcperm = 1;
ctxt->svcperm = true;
}
return 1;
}
@@ -367,7 +441,7 @@ static int _config_debugmode(launch_ctxt_t *ctxt, const char *value)
if (*value == '1')
{
DPRINTF("Enabled Debug mode\n");
ctxt->debugmode = 1;
ctxt->debugmode = true;
}
return 1;
}
@@ -377,7 +451,37 @@ static int _config_atmosphere(launch_ctxt_t *ctxt, const char *value)
if (*value == '1')
{
DPRINTF("Enabled atmosphere patching\n");
ctxt->atmosphere = 1;
ctxt->atmosphere = true;
}
return 1;
}
static int _config_kip1patch(launch_ctxt_t *ctxt, const char *value)
{
if (value == NULL)
return 0;
int valueLen = strlen(value);
if (!valueLen)
return 0;
if (ctxt->kip1_patches == NULL)
{
ctxt->kip1_patches = malloc(valueLen + 1);
memcpy(ctxt->kip1_patches, value, valueLen);
ctxt->kip1_patches[valueLen] = 0;
}
else
{
char *oldAlloc = ctxt->kip1_patches;
int oldSize = strlen(oldAlloc);
ctxt->kip1_patches = malloc(oldSize + 1 + valueLen + 1);
memcpy(ctxt->kip1_patches, oldAlloc, oldSize);
free(oldAlloc);
oldAlloc = NULL;
ctxt->kip1_patches[oldSize++] = ',';
memcpy(&ctxt->kip1_patches[oldSize], value, valueLen);
ctxt->kip1_patches[oldSize + valueLen] = 0;
}
return 1;
}
@@ -393,6 +497,7 @@ static const cfg_handler_t _config_handlers[] = {
{ "secmon", _config_secmon },
{ "kernel", _config_kernel },
{ "kip1", _config_kip1 },
{ "kip1patch", _config_kip1patch },
{ "fullsvcperm", _config_svcperm },
{ "debugmode", _config_debugmode },
{ "atmosphere", _config_atmosphere },
@@ -402,10 +507,15 @@ static const cfg_handler_t _config_handlers[] = {
static int _config(launch_ctxt_t *ctxt, ini_sec_t *cfg)
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg->kvs, link)
{
for(u32 i = 0; _config_handlers[i].key; i++)
if (!strcmp(_config_handlers[i].key, kv->key) &&
!_config_handlers[i].handler(ctxt, kv->val))
return 0;
{
if (!strcmp(_config_handlers[i].key, kv->key))
if (!_config_handlers[i].handler(ctxt, kv->val))
return 0;
}
}
return 1;
}
@@ -417,6 +527,7 @@ static void _free_launch_components(launch_ctxt_t *ctxt)
free(ctxt->warmboot);
free(ctxt->secmon);
free(ctxt->kernel);
free(ctxt->kip1_patches);
}
int hos_launch(ini_sec_t *cfg)
@@ -424,7 +535,6 @@ int hos_launch(ini_sec_t *cfg)
int bootStateDramPkg2 = 0;
int bootStatePkg2Continue = 0;
int exoFwNumber = 0;
int end_di = 0;
launch_ctxt_t ctxt;
memset(&ctxt, 0, sizeof(launch_ctxt_t));
@@ -484,7 +594,8 @@ int hos_launch(ini_sec_t *cfg)
gfx_printf(&gfx_con, "Loaded warmboot.bin and secmon\n");
// Read package2.
if (!_read_emmc_pkg2(&ctxt))
u8 *bootConfigBuf = _read_emmc_pkg2(&ctxt);
if (!bootConfigBuf)
return 0;
gfx_printf(&gfx_con, "Read package2\n");
@@ -536,6 +647,15 @@ int hos_launch(ini_sec_t *cfg)
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
// Patch kip1s in memory if needed.
const char* unappliedPatch = pkg2_patch_kips(&kip1_info, ctxt.kip1_patches);
if (unappliedPatch != NULL)
{
gfx_printf(&gfx_con, "%kREQUESTED PATCH '%s' NOT APPLIED!%k\n", 0xFFFF0000, unappliedPatch, 0xFFCCCCCC);
sd_unmount(); // Just exiting is not enough until pkg2_patch_kips stops modifying the string passed into it.
while(1) {} // MUST stop here, because if user requests 'nogc' but it's not applied, their GC controller gets updated!
}
// Rebuild and encrypt package2.
pkg2_build_encrypt((void *)0xA9800000, ctxt.kernel, ctxt.kernel_size, &kip1_info);
gfx_printf(&gfx_con, "Rebuilt and loaded package2\n");
@@ -554,7 +674,7 @@ int hos_launch(ini_sec_t *cfg)
case KB_FIRMWARE_VERSION_100_200:
if (!exoFwNumber)
{
if(!strcmp(ctxt.pkg1_id->id, "20161121183008"))
if (!strcmp(ctxt.pkg1_id->id, "20161121183008"))
exoFwNumber = 1;
else
exoFwNumber = 2;
@@ -562,14 +682,13 @@ int hos_launch(ini_sec_t *cfg)
case KB_FIRMWARE_VERSION_300:
case KB_FIRMWARE_VERSION_301:
if (ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_300)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 security check.
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA address id.
else if (ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_301)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 security check.
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id.
se_key_acc_ctrl(12, 0xFF);
se_key_acc_ctrl(13, 0xFF);
bootStateDramPkg2 = 2;
bootStatePkg2Continue = 3;
end_di = 1;
if (!exoFwNumber)
exoFwNumber = 3;
break;
@@ -577,13 +696,16 @@ int hos_launch(ini_sec_t *cfg)
if (!exoFwNumber)
exoFwNumber = 4;
case KB_FIRMWARE_VERSION_500:
if (!exoFwNumber)
exoFwNumber = 5;
case KB_FIRMWARE_VERSION_600:
default:
se_key_acc_ctrl(12, 0xFF);
se_key_acc_ctrl(15, 0xFF);
bootStateDramPkg2 = 2;
bootStatePkg2Continue = 4;
if (!exoFwNumber)
exoFwNumber = 5;
exoFwNumber = 6;
break;
}
@@ -591,10 +713,20 @@ int hos_launch(ini_sec_t *cfg)
ini_free_section(cfg);
_free_launch_components(&ctxt);
// Copy BCT if debug mode is enabled.
memset((void *)0x4003D000, 0, 0x3000);
if(ctxt.debugmode)
_copy_bootconfig(&ctxt);
// Clear BCT area for retail units and copy it over if dev unit.
if (ctxt.pkg1_id->kb < KB_FIRMWARE_VERSION_600)
{
memset((void *)0x4003D000, 0, 0x3000);
if ((fuse_read_odm(4) & 3) == 3)
memcpy((void *)0x4003D000, bootConfigBuf, 0x1000);
}
else
{
memset((void *)0x4003F000, 0, 0x1000);
if ((fuse_read_odm(4) & 3) == 3)
memcpy((void *)0x4003F800, bootConfigBuf, 0x800);
}
free(bootConfigBuf);
// Config Exosphère if booting Atmosphère.
if (ctxt.atmosphere)
@@ -606,37 +738,30 @@ int hos_launch(ini_sec_t *cfg)
*mb_exo_fw_no = exoFwNumber;
}
// Lock SE before starting 'SecureMonitor'.
// Finalize MC carveout and lock SE before starting 'SecureMonitor'.
mc_config_carveout_finalize();
_se_lock();
//TODO: pkg1.1 locks PMC scratches, we can do that too at some point. For <4.0.0 after secmon?
//_pmc_scratch_lock(ctxt.pkg1_id->kb);
// < 4.0.0 Signals - 0: Nothing ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot.
// >= 4.0.0 Signals - 0: Nothing ready, 1: BCT ready, 2: DRAM ready, 4: pkg2 ready and continue boot.
vu32 *mb_in = (vu32 *)0x40002EF8;
//Non-zero: Secmon ready
// Non-zero: Secmon ready.
vu32 *mb_out = (vu32 *)0x40002EFC;
// Start from DRAM ready signal.
*mb_in = bootStateDramPkg2;
*mb_out = 0;
// Disable display. This must be executed before secmon to provide support for all fw versions.
display_end();
// Wait for secmon to get ready.
cluster_boot_cpu0(ctxt.pkg1_id->secmon_base);
while (!*mb_out)
usleep(1);
//TODO: pkg1.1 locks PMC scratches, we can do that too at some point.
/*PMC(0x4) = 0x7FFFF3;
PMC(0x2C4) = 0xFFFFFFFF;
PMC(0x2D8) = 0xFFAFFFFF;
PMC(0x5B0) = 0xFFFFFFFF;
PMC(0x5B4) = 0xFFFFFFFF;
PMC(0x5B8) = 0xFFFFFFFF;
PMC(0x5BC) = 0xFFFFFFFF;
PMC(0x5C0) = 0xFFAAFFFF;*/
//Disable display.
if (end_di)
display_end();
usleep(1); // This only works when in IRAM or with a trained DRAM.
// Signal pkg2 ready and continue boot.
*mb_in = bootStatePkg2Continue;

26
bootloader/hos/hos.h Normal file
View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _HOS_H_
#define _HOS_H_
#include "../utils/types.h"
#include "../config/ini.h"
int hos_launch(ini_sec_t *cfg);
int keygen(u8 *keyblob, u32 kb, void *tsec_fw);
#endif

97
ipl/pkg1.c → bootloader/hos/pkg1.c Executable file → Normal file
View File

@@ -1,29 +1,30 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* 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/>.
*/
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* 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 "pkg1.h"
#include "arm64.h"
#include "se.h"
#include "../utils/aarch64_util.h"
#include "../sec/se.h"
#define SM_100_ADR 0x4002B020
PATCHSET_DEF(_secmon_1_patchset,
//Patch the relocator to be able to run from SM_100_ADR.
// Patch the relocator to be able to run from SM_100_ADR.
{ 0x1E0, _ADRP(0, 0x7C013000 - _PAGEOFF(SM_100_ADR)) },
//Patch package2 decryption and signature/hash checks.
{ 0x9F0 + 0xADC, _NOP() }, //Header signature.
@@ -32,14 +33,14 @@ PATCHSET_DEF(_secmon_1_patchset,
);
PATCHSET_DEF(_secmon_2_patchset,
//Patch package2 decryption and signature/hash checks.
// Patch package2 decryption and signature/hash checks.
{ 0xAC8 + 0xAAC, _NOP() }, //Header signature.
{ 0xAC8 + 0xB3C, _NOP() }, //Version.
{ 0xAC8 + 0xB58, _NOP() } //Sections SHA2.
);
PATCHSET_DEF(_secmon_3_patchset,
//Patch package2 decryption and signature/hash checks.
// Patch package2 decryption and signature/hash checks.
{ 0xAC8 + 0xA30, _NOP() }, //Header signature.
{ 0xAC8 + 0xAB4, _NOP() }, //package2 structure.
{ 0xAC8 + 0xAC0, _NOP() }, //Version.
@@ -47,7 +48,7 @@ PATCHSET_DEF(_secmon_3_patchset,
);
PATCHSET_DEF(_secmon_4_patchset,
//Patch package2 decryption and signature/hash checks.
// Patch package2 decryption and signature/hash checks.
{ 0x2300 + 0x5D80, _NOP() }, //package2 structure.
{ 0x2300 + 0x5D8C, _NOP() }, //Version.
{ 0x2300 + 0x5EFC, _NOP() }, //Header signature.
@@ -55,31 +56,41 @@ PATCHSET_DEF(_secmon_4_patchset,
);
PATCHSET_DEF(_secmon_5_patchset,
//Patch package2 decryption and signature/hash checks.
{ 0xDA8 + 0x9D8 , _NOP() }, //package2 structure.
{ 0xDA8 + 0x9E4 , _NOP() }, //Version.
{ 0xDA8 + 0xC9C , _NOP() }, //Header signature.
{ 0xDA8 + 0x1038 , _NOP() } //Sections SHA2.
// Patch package2 decryption and signature/hash checks.
{ 0xDA8 + 0x9D8, _NOP() }, //package2 structure.
{ 0xDA8 + 0x9E4, _NOP() }, //Version.
{ 0xDA8 + 0xC9C, _NOP() }, //Header signature.
{ 0xDA8 + 0x1038, _NOP() } //Sections SHA2.
);
PATCHSET_DEF(_secmon_6_patchset,
// Patch package2 decryption and signature/hash checks.
{ 0xDC8 + 0x820, _NOP() }, //package2 structure.
{ 0xDC8 + 0x82C, _NOP() }, //Version.
{ 0xDC8 + 0xE90, _NOP() }, //Header signature.
{ 0xDC8 + 0x112C, _NOP() } //Sections SHA2.
);
/*
* package1.1 header: <wb, ldr, sm>
* package1.1 layout:
* 1.0: {sm, ldr, wb} { 2, 1, 0 }
* 2.0: {wb, ldr, sm} { 0, 1, 2 }
* 3.0: {wb, ldr, sm} { 0, 1, 2 }
* 3.1: {wb, ldr, sm} { 0, 1, 2 }
* 4.0: {ldr, sm, wb} { 1, 2, 0 }
* 5.0: {ldr, sm, wb} { 1, 2, 0 }
*/
* package1.1 header: <wb, ldr, sm>
* package1.1 layout:
* 1.0: {sm, ldr, wb} { 2, 1, 0 }
* 2.0: {wb, ldr, sm} { 0, 1, 2 }
* 3.0: {wb, ldr, sm} { 0, 1, 2 }
* 3.1: {wb, ldr, sm} { 0, 1, 2 }
* 4.0: {ldr, sm, wb} { 1, 2, 0 }
* 5.0: {ldr, sm, wb} { 1, 2, 0 }
* 6.0: {ldr, sm, wb} { 1, 2, 0 }
*/
static const pkg1_id_t _pkg1_ids[] = {
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, 1, _secmon_1_patchset }, //1.0.0 (Patched relocator)
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_2_patchset }, //2.0.0 - 2.3.0
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_3_patchset }, //3.0.0
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_3_patchset }, //3.0.1 - 3.0.2
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, 0, _secmon_4_patchset }, //4.0.0 - 4.1.0
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, 0, _secmon_5_patchset }, //5.0.0 - 5.1.0
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, true, _secmon_1_patchset }, //1.0.0 (Patched relocator)
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_2_patchset }, //2.0.0 - 2.3.0
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset }, //3.0.0
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset }, //3.0.1 - 3.0.2
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_4_patchset }, //4.0.0 - 4.1.0
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_5_patchset }, //5.0.0 - 5.1.0
{ "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_6_patchset }, //6.0.0 - 6.0.0
{ NULL } //End.
};
@@ -94,7 +105,7 @@ const pkg1_id_t *pkg1_identify(u8 *pkg1)
void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
{
//Decrypt package1.
// Decrypt package1.
u8 *pkg11 = pkg1 + id->pkg11_off;
u32 pkg11_size = *(u32 *)pkg11;
se_aes_crypt_ctr(11, pkg11 + 0x20, pkg11_size, pkg11 + 0x20, pkg11_size, pkg11 + 0x10);

32
ipl/pkg1.h → bootloader/hos/pkg1.h Executable file → Normal file
View File

@@ -1,23 +1,23 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 _PKG1_H_
#define _PKG1_H_
#include "types.h"
#include "../utils/types.h"
typedef struct _patch_t
{
@@ -40,7 +40,7 @@ typedef struct _pkg1_id_t
u32 sec_map[3];
u32 secmon_base;
u32 warmboot_base;
int set_warmboot;
bool set_warmboot;
patch_t *secmon_patchset;
} pkg1_id_t;

902
bootloader/hos/pkg2.c Normal file
View File

@@ -0,0 +1,902 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018 Atmosphère-NX
*
* 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 "pkg2.h"
#include "../utils/aarch64_util.h"
#include "../mem/heap.h"
#include "../sec/se.h"
#include "../libs/compr/blz.h"
#include "../gfx/gfx.h"
extern gfx_con_t gfx_con;
/*#include "util.h"
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
#define DEBUG_PRINTING*/
#define DPRINTF(...)
//TODO: Replace hardcoded AArch64 instructions with instruction macros.
//TODO: Reduce hardcoded values without searching kernel for patterns?
// The process ID send/receive kernel patches were taken from Atmosphère's kernel patches.
// They should only be used when running Atmosphère.
#define FREE_CODE_OFF_1ST_100 0x4797C
#define FREE_CODE_OFF_1ST_200 0x6486C
#define FREE_CODE_OFF_1ST_300 0x494A4
#define FREE_CODE_OFF_1ST_302 0x494BC
#define FREE_CODE_OFF_1ST_400 0x52890
#define FREE_CODE_OFF_1ST_500 0x5C020
#define FREE_CODE_OFF_1ST_600 0x5EE00
#define ID_SND_OFF_100 0x23CC0
#define ID_SND_OFF_200 0x3F134
#define ID_SND_OFF_300 0x26080
#define ID_SND_OFF_302 0x26080
#define ID_SND_OFF_400 0x2AF64
#define ID_SND_OFF_500 0x2AD34
#define ID_SND_OFF_600 0x2BB8C
#define ID_RCV_OFF_100 0x219F0
#define ID_RCV_OFF_200 0x3D1A8
#define ID_RCV_OFF_300 0x240F0
#define ID_RCV_OFF_302 0x240F0
#define ID_RCV_OFF_400 0x28F6C
#define ID_RCV_OFF_500 0x28DAC
#define ID_RCV_OFF_600 0x29B6C
static u32 PRC_ID_SND_100[] =
{
0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B,
0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA
};
#define FREE_CODE_OFF_2ND_100 (FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100) + 4)
static u32 PRC_ID_RCV_100[] =
{
0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A,
0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA
};
static u32 PRC_ID_SND_200[] =
{
0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B,
0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA
};
#define FREE_CODE_OFF_2ND_200 (FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200) + 4)
static u32 PRC_ID_RCV_200[] =
{
0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148,
0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA
};
static u32 PRC_ID_SND_300[] =
{
0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B,
0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA
};
#define FREE_CODE_OFF_2ND_300 (FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300) + 4)
static u32 PRC_ID_RCV_300[] =
{
0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148,
0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA
};
static u32 PRC_ID_SND_302[] =
{
0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B,
0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA
};
#define FREE_CODE_OFF_2ND_302 (FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_302) + 4)
static u32 PRC_ID_RCV_302[] =
{
0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148,
0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA
};
static u32 PRC_ID_SND_400[] =
{
0x2A1703EA, 0xD37EF54A, 0xF86A6B8A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9,
0xEB09015F, 0x54000060, 0xF94053EA, 0xF9415948, 0xF94053EA
};
#define FREE_CODE_OFF_2ND_400 (FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400) + 4)
static u32 PRC_ID_RCV_400[] =
{
0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A,
0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F
};
static u32 PRC_ID_SND_500[] =
{
0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9,
0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA
};
#define FREE_CODE_OFF_2ND_500 (FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500) + 4)
static u32 PRC_ID_RCV_500[] =
{
0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A,
0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA
};
static u32 PRC_ID_SND_600[] =
{
0xA9BF2FEA, 0xF94037EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0,
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
};
#define FREE_CODE_OFF_2ND_600 (FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600) + 4)
static u32 PRC_ID_RCV_600[] =
{
0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0,
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
};
// Include kernel patches here, so we can utilize pkg1 id
KERNEL_PATCHSET_DEF(_kernel_1_patchset,
{ SVC_VERIFY_DS, 0x3764C, _NOP(), NULL }, // Disable SVC verifications
{ DEBUG_MODE_EN, 0x44074, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
// Atmosphère kernel patches.
{ ATM_GEN_PATCH, ID_SND_OFF_100, _B(ID_SND_OFF_100, FREE_CODE_OFF_1ST_100), NULL}, // Send process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_100, sizeof(PRC_ID_SND_100) >> 2, PRC_ID_SND_100}, // Send process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100), // Branch back and skip 1 instruction.
_B(FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100), ID_SND_OFF_100 + 4), NULL},
{ ATM_GEN_PATCH, ID_RCV_OFF_100, _B(ID_RCV_OFF_100, FREE_CODE_OFF_2ND_100), NULL}, // Receive process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_100, sizeof(PRC_ID_RCV_100) >> 2, PRC_ID_RCV_100}, // Receive process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_100 + sizeof(PRC_ID_RCV_100), // Branch back and skip 1 instruction.
_B(FREE_CODE_OFF_2ND_100 + sizeof(PRC_ID_RCV_100), ID_RCV_OFF_100 + 4), NULL}
);
KERNEL_PATCHSET_DEF(_kernel_2_patchset,
{ SVC_VERIFY_DS, 0x54834, _NOP(), NULL }, // Disable SVC verifications
{ DEBUG_MODE_EN, 0x6086C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
// Atmosphère kernel patches.
{ ATM_GEN_PATCH, ID_SND_OFF_200, _B(ID_SND_OFF_200, FREE_CODE_OFF_1ST_200), NULL}, // Send process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_200, sizeof(PRC_ID_SND_200) >> 2, PRC_ID_SND_200}, // Send process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200), // Branch back and skip 1 instruction.
_B(FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200), ID_SND_OFF_200 + 4), NULL},
{ ATM_GEN_PATCH, ID_RCV_OFF_200, _B(ID_RCV_OFF_200, FREE_CODE_OFF_2ND_200), NULL}, // Receive process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_200, sizeof(PRC_ID_RCV_200) >> 2, PRC_ID_RCV_200}, // Receive process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_200 + sizeof(PRC_ID_RCV_200), // Branch back and skip 1 instruction.
_B(FREE_CODE_OFF_2ND_200 + sizeof(PRC_ID_RCV_200), ID_RCV_OFF_200 + 4), NULL}
);
KERNEL_PATCHSET_DEF(_kernel_3_patchset,
{ SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications
{ DEBUG_MODE_EN, 0x483FC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
// Atmosphère kernel patches.
{ ATM_GEN_PATCH, ID_SND_OFF_300, _B(ID_SND_OFF_300, FREE_CODE_OFF_1ST_300), NULL}, // Send process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_300, sizeof(PRC_ID_SND_300) >> 2, PRC_ID_SND_300}, // Send process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300), // Branch back and skip 1 instruction.
_B(FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300), ID_SND_OFF_300 + 4), NULL},
{ ATM_GEN_PATCH, ID_RCV_OFF_300, _B(ID_RCV_OFF_300, FREE_CODE_OFF_2ND_300), NULL}, // Receive process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_300, sizeof(PRC_ID_RCV_300) >> 2, PRC_ID_RCV_300}, // Receive process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_300 + sizeof(PRC_ID_RCV_300), // Branch back and skip 1 instruction.
_B(FREE_CODE_OFF_2ND_300 + sizeof(PRC_ID_RCV_300), ID_RCV_OFF_300 + 4), NULL}
);
KERNEL_PATCHSET_DEF(_kernel_302_patchset,
{ SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications
{ DEBUG_MODE_EN, 0x48414, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
// Atmosphère kernel patches.
{ ATM_GEN_PATCH, ID_SND_OFF_302, _B(ID_SND_OFF_302, FREE_CODE_OFF_1ST_302), NULL}, // Send process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_302, sizeof(PRC_ID_SND_302) >> 2, PRC_ID_SND_302}, // Send process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_302), // Branch back and skip 1 instruction.
_B(FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_302), ID_SND_OFF_302 + 4), NULL},
{ ATM_GEN_PATCH, ID_RCV_OFF_302, _B(ID_RCV_OFF_302, FREE_CODE_OFF_2ND_302), NULL}, // Receive process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_302, sizeof(PRC_ID_RCV_302) >> 2, PRC_ID_RCV_302}, // Receive process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_302 + sizeof(PRC_ID_RCV_302), // Branch back and skip 1 instruction.
_B(FREE_CODE_OFF_2ND_302 + sizeof(PRC_ID_RCV_302), ID_RCV_OFF_302 + 4), NULL}
);
KERNEL_PATCHSET_DEF(_kernel_4_patchset,
{ SVC_VERIFY_DS, 0x41EB4, _NOP(), NULL }, // Disable SVC verifications
{ DEBUG_MODE_EN, 0x4EBFC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
// Atmosphère kernel patches.
{ ATM_GEN_PATCH, ID_SND_OFF_400, _B(ID_SND_OFF_400, FREE_CODE_OFF_1ST_400), NULL}, // Send process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_400, sizeof(PRC_ID_SND_400) >> 2, PRC_ID_SND_400}, // Send process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400), // Branch back and skip 2 instructions.
_B(FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400), ID_SND_OFF_400 + 8), NULL},
{ ATM_GEN_PATCH, ID_RCV_OFF_400, _B(ID_RCV_OFF_400, FREE_CODE_OFF_2ND_400), NULL}, // Receive process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_400, sizeof(PRC_ID_RCV_400) >> 2, PRC_ID_RCV_400}, // Receive process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_400 + sizeof(PRC_ID_RCV_400), // Branch back and skip 1 instruction.
_B(FREE_CODE_OFF_2ND_400 + sizeof(PRC_ID_RCV_400), ID_RCV_OFF_400 + 4), NULL}
);
KERNEL_PATCHSET_DEF(_kernel_5_patchset,
{ SVC_VERIFY_DS, 0x45E6C, _NOP(), NULL }, // Disable SVC verifications
{ DEBUG_MODE_EN, 0x5513C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
// Atmosphère kernel patches.
{ ATM_GEN_PATCH, ID_SND_OFF_500, _B(ID_SND_OFF_500, FREE_CODE_OFF_1ST_500), NULL}, // Send process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_500, sizeof(PRC_ID_SND_500) >> 2, PRC_ID_SND_500}, // Send process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500), // Branch back and skip 2 instructions.
_B(FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500), ID_SND_OFF_500 + 8), NULL},
{ ATM_GEN_PATCH, ID_RCV_OFF_500, _B(ID_RCV_OFF_500, FREE_CODE_OFF_2ND_500), NULL}, // Receive process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_500, sizeof(PRC_ID_RCV_500) >> 2, PRC_ID_RCV_500}, // Receive process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_500 + sizeof(PRC_ID_RCV_500), // Branch back and skip 2 instructions.
_B(FREE_CODE_OFF_2ND_500 + sizeof(PRC_ID_RCV_500), ID_RCV_OFF_500 + 8), NULL}
);
KERNEL_PATCHSET_DEF(_kernel_6_patchset,
{ SVC_VERIFY_DS, 0x47EA0, _NOP(), NULL }, // Disable SVC verifications
{ DEBUG_MODE_EN, 0x57548, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
// Atmosphère kernel patches.
{ ATM_GEN_PATCH, ID_SND_OFF_600, _B(ID_SND_OFF_600, FREE_CODE_OFF_1ST_600), NULL}, // Send process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_600, sizeof(PRC_ID_SND_600) >> 2, PRC_ID_SND_600}, // Send process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600), // Branch back and skip 4 instructions.
_B(FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600), ID_SND_OFF_600 + 0x10), NULL},
{ ATM_GEN_PATCH, ID_RCV_OFF_600, _B(ID_RCV_OFF_600, FREE_CODE_OFF_2ND_600), NULL}, // Receive process id branch.
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_600, sizeof(PRC_ID_RCV_600) >> 2, PRC_ID_RCV_600}, // Receive process id code.
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_600 + sizeof(PRC_ID_RCV_600), // Branch back and skip 4 instructions.
_B(FREE_CODE_OFF_2ND_600 + sizeof(PRC_ID_RCV_600), ID_RCV_OFF_600 + 0x10), NULL}
);
static const pkg2_kernel_id_t _pkg2_kernel_ids[] =
{
{ 0x427f2647, _kernel_1_patchset }, //1.0.0
{ 0xae19cf1b, _kernel_2_patchset }, //2.0.0 - 2.3.0
{ 0x73c9e274, _kernel_3_patchset }, //3.0.0 - 3.0.1
{ 0xe0e8cdc4, _kernel_302_patchset }, //3.0.2
{ 0x485d0157, _kernel_4_patchset }, //4.0.0 - 4.1.0
{ 0xf3c363f2, _kernel_5_patchset }, //5.0.0 - 5.1.0
{ 0x64ce1a44, _kernel_6_patchset }, //6.0.0
{ 0, 0 } //End.
};
enum kip_offset_section
{
KIP_TEXT = 0,
KIP_RODATA = 1,
KIP_DATA = 2,
KIP_BSS = 3,
KIP_UNKSEC1 = 4,
KIP_UNKSEC2 = 5
};
#define KIP_PATCH_SECTION_SHIFT (29)
#define KIP_PATCH_SECTION_MASK (7 << KIP_PATCH_SECTION_SHIFT)
#define KIP_PATCH_OFFSET_MASK (~KIP_PATCH_SECTION_MASK)
#define GET_KIP_PATCH_SECTION(x) ((x >> KIP_PATCH_SECTION_SHIFT) & 7)
#define GET_KIP_PATCH_OFFSET(x) (x & KIP_PATCH_OFFSET_MASK)
#define KPS(x) ((u32)(x) << KIP_PATCH_SECTION_SHIFT)
static kip1_patch_t _fs_nosigchk_100[] =
{
{ KPS(KIP_TEXT) | 0x194A0, 4, "\xBA\x09\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x3A79C, 4, "\xE0\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_100[] =
{
{ "nosigchk", _fs_nosigchk_100 },
{ "nogc", NULL },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_200[] =
{
{ KPS(KIP_TEXT) | 0x15DF4, 4, "\xBC\x0A\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x3F720, 4, "\x00\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_200[] =
{
{ "nosigchk", _fs_nosigchk_200 },
{ "nogc", NULL },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_210[] =
{
{ KPS(KIP_TEXT) | 0x15F64, 4, "\xDF\x0A\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x3FAF8, 4, "\x00\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_210[] =
{
{ "nosigchk", _fs_nosigchk_210 },
{ "nogc", NULL },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_300[] =
{
{ KPS(KIP_TEXT) | 0x18E24, 4, "\x52\x0C\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x49EC8, 4, "\x40\x04\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_300[] =
{
{ "nosigchk", _fs_nosigchk_300 },
{ "nogc", NULL },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_30x[] =
{
{ KPS(KIP_TEXT) | 0x18E90, 4, "\x52\x0C\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x49F34, 4, "\xE0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_30x[] =
{
{ "nosigchk", _fs_nosigchk_30x },
{ "nogc", NULL },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_4xx[] =
{
{ KPS(KIP_TEXT) | 0x1C4FC, 4, "\x3C\x2F\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x57934, 4, "\xE0\x02\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_40x[] =
{
{ KPS(KIP_TEXT) | 0xA3458, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" },
{ KPS(KIP_TEXT) | 0xAAB44, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_40x[] =
{
{ "nosigchk", _fs_nosigchk_4xx },
{ "nogc", _fs_nogc_40x },
{ NULL, NULL }
};
static kip1_patch_t _fs_nogc_410[] =
{
{ KPS(KIP_TEXT) | 0xA34BC, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" },
{ KPS(KIP_TEXT) | 0xAABA8, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_410[] =
{
{ "nosigchk", _fs_nosigchk_4xx },
{ "nogc", _fs_nogc_410 },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_50x[] =
{
{ KPS(KIP_TEXT) | 0x22DDC, 4, "\x7D\x3E\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x7D490, 4, "\x40\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_50x[] =
{
{ KPS(KIP_TEXT) | 0xCF3C4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
{ KPS(KIP_TEXT) | 0xD73A0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_50x[] =
{
{ "nosigchk", _fs_nosigchk_50x },
{ "nogc", _fs_nogc_50x },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_510[] =
{
{ KPS(KIP_TEXT) | 0x22E0C, 4, "\x85\x3E\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x7D860, 4, "\x40\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_510[] =
{
{ KPS(KIP_TEXT) | 0xCF794, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
{ KPS(KIP_TEXT) | 0xD7770, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_510[] =
{
{ "nosigchk", _fs_nosigchk_510 },
{ "nogc", _fs_nogc_510 },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_600[] =
{
{ KPS(KIP_TEXT) | 0x712A8, 4, "\x8E\x3E\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0xEB08C, 4, "\xC0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_600_exfat[] =
{
{ KPS(KIP_TEXT) | 0x7C9A8, 4, "\x8E\x3E\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0xF678C, 4, "\xC0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_600[] =
{
{ KPS(KIP_TEXT) | 0x12CC20, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
{ KPS(KIP_TEXT) | 0x1538F4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_600_exfat[] =
{
{ KPS(KIP_TEXT) | 0x138320, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
{ KPS(KIP_TEXT) | 0x15EFF4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_600[] =
{
{ "nosigchk", _fs_nosigchk_600 },
{ "nogc", _fs_nogc_600 },
{ NULL, NULL }
};
static kip1_patchset_t _fs_patches_600_exfat[] =
{
{ "nosigchk", _fs_nosigchk_600_exfat },
{ "nogc", _fs_nogc_600_exfat },
{ NULL, NULL }
};
static kip1_id_t _kip_ids[] =
{
{ "FS", "\xde\x9f\xdd\xa4\x08\x5d\xd5\xfe\x68\xdc\xb2\x0b\x41\x09\x5b\xb4", _fs_patches_100 }, // FS 1.0.0
{ "FS", "\xfc\x3e\x80\x99\x1d\xca\x17\x96\x4a\x12\x1f\x04\xb6\x1b\x17\x5e", _fs_patches_100 }, // FS 1.0.0 exfat
{ "FS", "\xcd\x7b\xbe\x18\xd6\x13\x0b\x28\xf6\x2f\x19\xfa\x79\x45\x53\x5b", _fs_patches_200 }, // FS 2.0.0
{ "FS", "\xe7\x66\x92\xdf\xaa\x04\x20\xe9\xfd\xd6\x8e\x43\x63\x16\x18\x18", _fs_patches_200 }, // FS 2.0.0 exfat
{ "FS", "\x0d\x70\x05\x62\x7b\x07\x76\x7c\x0b\x96\x3f\x9a\xff\xdd\xe5\x66", _fs_patches_210 }, // FS 2.1.0
{ "FS", "\xdb\xd8\x5f\xca\xcc\x19\x3d\xa8\x30\x51\xc6\x64\xe6\x45\x2d\x32", _fs_patches_210 }, // FS 2.1.0 exfat
{ "FS", "\xa8\x6d\xa5\xe8\x7e\xf1\x09\x7b\x23\xda\xb5\xb4\xdb\xba\xef\xe7", _fs_patches_300 }, // FS 3.0.0
{ "FS", "\x98\x1c\x57\xe7\xf0\x2f\x70\xf7\xbc\xde\x75\x31\x81\xd9\x01\xa6", _fs_patches_300 }, // FS 3.0.0 exfat
{ "FS", "\x57\x39\x7c\x06\x3f\x10\xb6\x31\x3f\x4d\x83\x76\x53\xcc\xc3\x71", _fs_patches_30x }, // FS 3.0.1
{ "FS", "\x07\x30\x99\xd7\xc6\xad\x7d\x89\x83\xbc\x7a\xdd\x93\x2b\xe3\xd1", _fs_patches_30x }, // FS 3.0.1 exfat
{ "FS", "\x06\xe9\x07\x19\x59\x5a\x01\x0c\x62\x46\xff\x70\x94\x6f\x10\xfb", _fs_patches_40x }, // FS 4.0.1
{ "FS", "\x54\x9b\x0f\x8d\x6f\x72\xc4\xe9\xf3\xfd\x1f\x19\xea\xce\x4a\x5a", _fs_patches_40x }, // FS 4.0.1 exfat
{ "FS", "\x80\x96\xaf\x7c\x6a\x35\xaa\x82\x71\xf3\x91\x69\x95\x41\x3b\x0b", _fs_patches_410 }, // FS 4.1.0
{ "FS", "\x02\xd5\xab\xaa\xfd\x20\xc8\xb0\x63\x3a\xa0\xdb\xae\xe0\x37\x7e", _fs_patches_410 }, // FS 4.1.0 exfat
{ "FS", "\xa6\xf2\x7a\xd9\xac\x7c\x73\xad\x41\x9b\x63\xb2\x3e\x78\x5a\x0c", _fs_patches_50x }, // FS 5.0.0
{ "FS", "\xce\x3e\xcb\xa2\xf2\xf0\x62\xf5\x75\xf8\xf3\x60\x84\x2b\x32\xb4", _fs_patches_50x }, // FS 5.0.0 exfat
{ "FS", "\x76\xf8\x74\x02\xc9\x38\x7c\x0f\x0a\x2f\xab\x1b\x45\xce\xbb\x93", _fs_patches_510 }, // FS 5.1.0
{ "FS", "\x10\xb2\xd8\x16\x05\x48\x85\x99\xdf\x22\x42\xcb\x6b\xac\x2d\xf1", _fs_patches_510 }, // FS 5.1.0 exfat
{ "FS", "\x1b\x82\xcb\x22\x18\x67\xcb\x52\xc4\x4a\x86\x9e\xa9\x1a\x1a\xdd", _fs_patches_600 }, // FS 6.0.0-4.0
{ "FS", "\x96\x6a\xdd\x3d\x20\xb6\x27\x13\x2c\x5a\x8d\xa4\x9a\xc9\xd8\xdd", _fs_patches_600_exfat }, // FS 6.0.0-4.0 exfat
{ "FS", "\x3a\x57\x4d\x43\x61\x86\x19\x1d\x17\x88\xeb\x2c\x0f\x07\x6b\x11", _fs_patches_600 }, // FS 6.0.0-5.0
{ "FS", "\x33\x05\x53\xf6\xb5\xfb\x55\xc4\xc2\xd7\xb7\x36\x24\x02\x76\xb3", _fs_patches_600_exfat } // FS 6.0.0-5.0 exfat
};
const pkg2_kernel_id_t *pkg2_identify(u32 id)
{
for (u32 i = 0; _pkg2_kernel_ids[i].crc32c_id; i++)
if (id == _pkg2_kernel_ids[i].crc32c_id)
return &_pkg2_kernel_ids[i];
return NULL;
}
static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1)
{
u32 size = sizeof(pkg2_kip1_t);
for (u32 j = 0; j < KIP1_NUM_SECTIONS; j++)
size += kip1->sections[j].size_comp;
return size;
}
void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2)
{
u8 *ptr = pkg2->data + pkg2->sec_size[PKG2_SEC_KERNEL];
pkg2_ini1_t *ini1 = (pkg2_ini1_t *)ptr;
ptr += sizeof(pkg2_ini1_t);
for (u32 i = 0; i < ini1->num_procs; i++)
{
pkg2_kip1_t *kip1 = (pkg2_kip1_t *)ptr;
pkg2_kip1_info_t *ki = (pkg2_kip1_info_t *)malloc(sizeof(pkg2_kip1_info_t));
ki->kip1 = kip1;
ki->size = _pkg2_calc_kip1_size(kip1);
list_append(info, &ki->link);
ptr += ki->size;
DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size);
}
}
int pkg2_has_kip(link_t *info, u64 tid)
{
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
if(ki->kip1->tid == tid)
return 1;
return 0;
}
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1)
{
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
if (ki->kip1->tid == tid)
{
ki->kip1 = kip1;
ki->size = _pkg2_calc_kip1_size(kip1);
DPRINTF("replaced kip (new size %08X)\n", ki->size);
return;
}
}
void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1)
{
pkg2_kip1_info_t *ki = (pkg2_kip1_info_t *)malloc(sizeof(pkg2_kip1_info_t));
ki->kip1 = kip1;
ki->size = _pkg2_calc_kip1_size(kip1);
DPRINTF("added kip (size %08X)\n", ki->size);
list_append(info, &ki->link);
}
void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1)
{
if (pkg2_has_kip(info, kip1->tid))
pkg2_replace_kip(info, kip1->tid, kip1);
else
pkg2_add_kip(info, kip1);
}
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp)
{
u32 compClearMask = ~sectsToDecomp;
if ((ki->kip1->flags & compClearMask) == ki->kip1->flags)
return 0; // Already decompressed, nothing to do.
pkg2_kip1_t hdr;
memcpy(&hdr, ki->kip1, sizeof(hdr));
unsigned int newKipSize = sizeof(hdr);
for (u32 sectIdx=0; sectIdx<KIP1_NUM_SECTIONS; sectIdx++)
{
u32 sectCompBit = 1u << sectIdx;
// For compressed, cant get actual decompressed size without doing it, so use safe "output size".
if (sectIdx < 3 && (sectsToDecomp & sectCompBit) && (hdr.flags & sectCompBit))
newKipSize += hdr.sections[sectIdx].size_decomp;
else
newKipSize += hdr.sections[sectIdx].size_comp;
}
pkg2_kip1_t* newKip = malloc(newKipSize);
unsigned char* dstDataPtr = newKip->data;
const unsigned char* srcDataPtr = ki->kip1->data;
for (u32 sectIdx=0; sectIdx<KIP1_NUM_SECTIONS; sectIdx++)
{
u32 sectCompBit = 1u << sectIdx;
// Easy copy path for uncompressed or ones we dont want to uncompress.
if (sectIdx >= 3 || !(sectsToDecomp & sectCompBit) || !(hdr.flags & sectCompBit))
{
unsigned int dataSize = hdr.sections[sectIdx].size_comp;
if (dataSize == 0)
continue;
memcpy(dstDataPtr, srcDataPtr, dataSize);
srcDataPtr += dataSize;
dstDataPtr += dataSize;
continue;
}
unsigned int compSize = hdr.sections[sectIdx].size_comp;
unsigned int outputSize = hdr.sections[sectIdx].size_decomp;
gfx_printf(&gfx_con, "Decomping %s KIP1 sect %d of size %d...\n", (const char*)hdr.name, sectIdx, compSize);
if (blz_uncompress_srcdest(srcDataPtr, compSize, dstDataPtr, outputSize) == 0)
{
gfx_printf(&gfx_con, "%kERROR decomping sect %d of %s KIP!%k\n", 0xFFFF0000, sectIdx, (char*)hdr.name, 0xFFCCCCCC);
free(newKip);
return 1;
}
else
{
DPRINTF("Done! Decompressed size is %d!\n", outputSize);
}
hdr.sections[sectIdx].size_comp = outputSize;
srcDataPtr += compSize;
dstDataPtr += outputSize;
}
hdr.flags &= compClearMask;
memcpy(newKip, &hdr, sizeof(hdr));
newKipSize = dstDataPtr-(unsigned char*)(newKip);
free(ki->kip1);
ki->kip1 = newKip;
ki->size = newKipSize;
return 0;
}
const char* pkg2_patch_kips(link_t *info, char* patchNames)
{
if (patchNames == NULL || patchNames[0] == 0)
return NULL;
static const u32 MAX_NUM_PATCHES_REQUESTED = sizeof(u32)*8;
char* patches[MAX_NUM_PATCHES_REQUESTED];
u32 numPatches=1;
patches[0] = patchNames;
{
for (char* p = patchNames; *p != 0; p++)
{
if (*p == ',')
{
*p = 0;
patches[numPatches++] = p+1;
if (numPatches >= MAX_NUM_PATCHES_REQUESTED)
return "too_many_patches";
}
else if (*p >= 'A' && *p <= 'Z')
*p += 0x20;
}
}
u32 patchesApplied = 0; // Bitset over patches.
for (u32 i=0; i<numPatches; i++)
{
// Eliminate leading spaces.
for (const char* p=patches[i]; *p!=0; p++)
{
if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
patches[i]++;
else
break;
}
int valueLen = strlen(patches[i]);
if (valueLen == 0)
continue;
// Eliminate trailing spaces.
for (int chIdx=valueLen-1; chIdx>=0; chIdx--)
{
const char* p = patches[i] + chIdx;
if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
valueLen = chIdx;
else
break;
}
patches[i][valueLen] = 0;
DPRINTF("Requested patch: '%s'\n", patches[i]);
}
u32 shaBuf[32/sizeof(u32)];
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
{
shaBuf[0] = 0; // sha256 for this kip not yet calculated.
for (u32 currKipIdx=0; currKipIdx<(sizeof(_kip_ids)/sizeof(_kip_ids[0])); currKipIdx++)
{
if (strncmp((const char*)ki->kip1->name, _kip_ids[currKipIdx].name, sizeof(ki->kip1->name)) != 0)
continue;
u32 bitsAffected = 0;
kip1_patchset_t* currPatchset = _kip_ids[currKipIdx].patchset;
while (currPatchset != NULL && currPatchset->name != NULL)
{
for (u32 i=0; i<numPatches; i++)
{
if (strcmp(currPatchset->name, patches[i]) != 0)
{
bitsAffected = i + 1;
break;
}
}
currPatchset++;
}
// Dont bother even hashing this KIP if we dont have any patches enabled for it.
if (bitsAffected == 0)
continue;
if (shaBuf[0] == 0)
{
if (!se_calc_sha256(shaBuf, ki->kip1, ki->size))
memset(shaBuf, 0, sizeof(shaBuf));
}
if (memcmp(shaBuf, _kip_ids[currKipIdx].hash, sizeof(_kip_ids[0].hash)) != 0)
continue;
// Find out which sections are affected by the enabled patches, to know which to decompress.
bitsAffected = 0;
currPatchset = _kip_ids[currKipIdx].patchset;
while (currPatchset != NULL && currPatchset->name != NULL)
{
if (currPatchset->patches != NULL)
{
for (u32 currEnabIdx=0; currEnabIdx<numPatches; currEnabIdx++)
{
if (strcmp(currPatchset->name, patches[currEnabIdx]))
continue;
for (const kip1_patch_t* currPatch=currPatchset->patches; currPatch != NULL && currPatch->length != 0; currPatch++)
bitsAffected |= 1u << GET_KIP_PATCH_SECTION(currPatch->offset);
}
}
currPatchset++;
}
// Got patches to apply to this kip, have to decompress it.
#ifdef DEBUG_PRINTING
u32 preDecompTime = get_tmr_us();
#endif
if (pkg2_decompress_kip(ki, bitsAffected))
return (const char*)ki->kip1->name; // Failed to decompress.
#ifdef DEBUG_PRINTING
u32 postDecompTime = get_tmr_us();
if (!se_calc_sha256(shaBuf, ki->kip1, ki->size))
memset(shaBuf, 0, sizeof(shaBuf));
DPRINTF("%dms %s KIP1 size %d hash %08X\n", (postDecompTime-preDecompTime)/1000, ki->kip1->name, (int)ki->size, __builtin_bswap32(shaBuf[0]));
#endif
currPatchset = _kip_ids[currKipIdx].patchset;
while (currPatchset != NULL && currPatchset->name != NULL)
{
for (u32 currEnabIdx=0; currEnabIdx<numPatches; currEnabIdx++)
{
if (strcmp(currPatchset->name, patches[currEnabIdx]))
continue;
u32 appliedMask = 1u << currEnabIdx;
if (currPatchset->patches == NULL)
{
gfx_printf(&gfx_con, "Patch '%s' not necessary for %s KIP1\n", currPatchset->name, (const char*)ki->kip1->name);
patchesApplied |= appliedMask;
break;
}
unsigned char* kipSectData = ki->kip1->data;
for (u32 currSectIdx=0; currSectIdx<KIP1_NUM_SECTIONS; currSectIdx++)
{
if (bitsAffected & (1u << currSectIdx))
{
gfx_printf(&gfx_con, "Applying patch '%s' on %s KIP1 sect %d\n", currPatchset->name, (const char*)ki->kip1->name, currSectIdx);
for (const kip1_patch_t* currPatch=currPatchset->patches;currPatch != NULL && currPatch->length != 0; currPatch++)
{
if (GET_KIP_PATCH_SECTION(currPatch->offset) != currSectIdx)
continue;
u32 currOffset = GET_KIP_PATCH_OFFSET(currPatch->offset);
if (memcmp(&kipSectData[currOffset], currPatch->srcData, currPatch->length) != 0)
{
gfx_printf(&gfx_con, "%kDATA MISMATCH FOR PATCH AT OFFSET 0x%x!!!%k\n", 0xFFFF0000, currOffset, 0xFFCCCCCC);
return currPatchset->name; // MUST stop here as kip is likely corrupt.
}
else
{
DPRINTF("Patching %d bytes at offset 0x%x\n", currPatch->length, currOffset);
memcpy(&kipSectData[currOffset], currPatch->dstData, currPatch->length);
}
}
}
kipSectData += ki->kip1->sections[currSectIdx].size_comp;
}
patchesApplied |= appliedMask;
break;
}
currPatchset++;
}
}
}
for (u32 i=0; i<numPatches; i++)
{
if ((patchesApplied & (1u << i)) == 0)
return patches[i];
}
return NULL;
}
pkg2_hdr_t *pkg2_decrypt(void *data)
{
u8 *pdata = (u8 *)data;
// Skip signature.
pdata += 0x100;
pkg2_hdr_t *hdr = (pkg2_hdr_t *)pdata;
// Skip header.
pdata += sizeof(pkg2_hdr_t);
// Decrypt header.
se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
//gfx_hexdump(&gfx_con, (u32)hdr, hdr, 0x100);
if (hdr->magic != PKG2_MAGIC)
return NULL;
for (u32 i = 0; i < 4; i++)
{
DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
if (!hdr->sec_size[i])
continue;
se_aes_crypt_ctr(8, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
//gfx_hexdump(&gfx_con, (u32)pdata, pdata, 0x100);
pdata += hdr->sec_size[i];
}
return hdr;
}
void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info)
{
u8 *pdst = (u8 *)dst;
// Signature.
memset(pdst, 0, 0x100);
pdst += 0x100;
// Header.
pkg2_hdr_t *hdr = (pkg2_hdr_t *)pdst;
memset(hdr, 0, sizeof(pkg2_hdr_t));
pdst += sizeof(pkg2_hdr_t);
hdr->magic = PKG2_MAGIC;
hdr->base = 0x10000000;
DPRINTF("kernel @ %08X (%08X)\n", (u32)kernel, kernel_size);
// Kernel.
memcpy(pdst, kernel, kernel_size);
hdr->sec_size[PKG2_SEC_KERNEL] = kernel_size;
hdr->sec_off[PKG2_SEC_KERNEL] = 0x10000000;
se_aes_crypt_ctr(8, pdst, kernel_size, pdst, kernel_size, &hdr->sec_ctr[PKG2_SEC_KERNEL * 0x10]);
pdst += kernel_size;
DPRINTF("kernel encrypted\n");
// INI1.
u32 ini1_size = sizeof(pkg2_ini1_t);
pkg2_ini1_t *ini1 = (pkg2_ini1_t *)pdst;
memset(ini1, 0, sizeof(pkg2_ini1_t));
ini1->magic = INI1_MAGIC;
pdst += sizeof(pkg2_ini1_t);
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, kips_info, link)
{
DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", ki->kip1->name, (u32)ki->kip1, ki->size);
memcpy(pdst, ki->kip1, ki->size);
pdst += ki->size;
ini1_size += ki->size;
ini1->num_procs++;
}
ini1->size = ini1_size;
hdr->sec_size[PKG2_SEC_INI1] = ini1_size;
hdr->sec_off[PKG2_SEC_INI1] = 0x14080000;
se_aes_crypt_ctr(8, ini1, ini1_size, ini1, ini1_size, &hdr->sec_ctr[PKG2_SEC_INI1 * 0x10]);
DPRINTF("INI1 encrypted\n");
//Encrypt header.
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
memset(hdr->ctr, 0 , 0x10);
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
}

56
ipl/pkg2.h → bootloader/hos/pkg2.h Executable file → Normal file
View File

@@ -1,25 +1,25 @@
/*
* 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/>.
*/
* 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 _PKG2_H_
#define _PKG2_H_
#include "types.h"
#include "list.h"
#include "../utils/types.h"
#include "../utils/list.h"
#define PKG2_MAGIC 0x31324B50
#define PKG2_SEC_BASE 0x80000000
@@ -113,11 +113,33 @@ typedef struct _pkg2_kernel_id_t
kernel_patch_t *kernel_patchset;
} pkg2_kernel_id_t;
typedef struct _kip1_patch_t
{
u32 offset; //section+offset of patch to apply
u32 length; //in bytes, 0 means last patch
const char* srcData; //that must match
const char* dstData; //that it gets replaced by
} kip1_patch_t;
typedef struct _kip1_patchset_t
{
const char* name; //NULL means end
kip1_patch_t* patches; //NULL means not necessary
} kip1_patchset_t;
typedef struct _kip1_id_t
{
const char* name;
u8 hash[16];
kip1_patchset_t* patchset;
} kip1_id_t;
void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2);
int pkg2_has_kip(link_t *info, u64 tid);
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1);
void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1);
const char* pkg2_patch_kips(link_t *info, char* patchNames);
const pkg2_kernel_id_t *pkg2_identify(u32 id);
pkg2_hdr_t *pkg2_decrypt(void *data);

175
bootloader/ianos/ianos.c Normal file
View File

@@ -0,0 +1,175 @@
/*
* Copyright (c) 2018 M4xw
* 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 "ianos.h"
#include "../utils/types.h"
#include "../libs/elfload/elfload.h"
#include "../../common/common_module.h"
#include "../mem/heap.h"
#include "../gfx/gfx.h"
#define IRAM_LIB_ADDR 0x4002B000
#define DRAM_LIB_ADDR 0xE0000000
extern gfx_ctxt_t gfx_ctxt;
extern gfx_con_t gfx_con;
extern heap_t _heap;
extern void *sd_file_read(char *path);
extern bool sd_mount();
extern void sd_unmount();
void *elfBuf = NULL;
void *fileBuf = NULL;
static void _ianos_call_ep(moduleEntrypoint_t entrypoint, void *moduleConfig)
{
bdkParams_t bdkParameters = (bdkParams_t)malloc(sizeof(struct _bdkParams_t));
bdkParameters->gfxCon = &gfx_con;
bdkParameters->gfxCtx = &gfx_ctxt;
bdkParameters->memcpy = (memcpy_t)&memcpy;
bdkParameters->memset = (memset_t)&memset;
bdkParameters->sharedHeap = &_heap;
entrypoint(moduleConfig, bdkParameters);
}
static void *_ianos_alloc_cb(el_ctx *ctx, Elf_Addr phys, Elf_Addr virt, Elf_Addr size)
{
(void)ctx;
(void)phys;
(void)size;
return (void *)virt;
}
static bool _ianos_read_cb(el_ctx *ctx, void *dest, size_t numberBytes, size_t offset)
{
(void)ctx;
memcpy(dest, fileBuf + offset, numberBytes);
return true;
}
void ianos_print_error(int errorno)
{
switch (errorno)
{
case 1:
gfx_printf(&gfx_con, "Can't find library!\n");
break;
case 2:
gfx_printf(&gfx_con, "Cant init ELF context!\n");
break;
case 3:
gfx_printf(&gfx_con, "Cant alloc memory!\n");
break;
case 4:
gfx_printf(&gfx_con, "Error loading ELF!\n");
break;
case 5:
gfx_printf(&gfx_con, "Error relcating ELF!\n");
break;
}
}
//TODO: Support shared libraries.
int ianos_loader(bool sdmount, char *path, elfType_t type, void *moduleConfig)
{
int res = 0;
if (sdmount)
{
if (!sd_mount())
{
res = 0xFFFF;
goto elfLoadFinalOut;
}
}
fileBuf = sd_file_read(path);
if (sdmount)
sd_unmount();
if (!fileBuf)
{
res = 1;
goto elfLoadFinalOut;
}
el_ctx ctx;
ctx.pread = _ianos_read_cb;
if (el_init(&ctx))
{
res = 2;
goto elfLoadFinalOut;
}
// Set our relocated library's buffer.
switch (type & 0xFFFF)
{
case EXEC_ELF:
case AR64_ELF:
elfBuf = (void *)DRAM_LIB_ADDR;
sd_unmount();
break;
default:
elfBuf = memalign(ctx.align, ctx.memsz);
}
if (!elfBuf)
{
res = 3;
goto elfLoadFinalOut;
}
// Load and relocate library.
ctx.base_load_vaddr = ctx.base_load_paddr = (uintptr_t)elfBuf;
if (el_load(&ctx, _ianos_alloc_cb))
{
res = 4;
goto elfFreeOut;
}
if (el_relocate(&ctx))
{
res = 5;
goto elfFreeOut;
}
// Launch.
uintptr_t epaddr = ctx.ehdr.e_entry + (uintptr_t)elfBuf;
moduleEntrypoint_t ep = (moduleEntrypoint_t)epaddr;
_ianos_call_ep(ep, moduleConfig);
elfFreeOut:
if ((u32)elfBuf >= 0x90000000 && (u32)elfBuf <= DRAM_LIB_ADDR)
free(elfBuf);
free(fileBuf);
elfBuf = NULL;
fileBuf = NULL;
elfLoadFinalOut:
return res;
}

34
bootloader/ianos/ianos.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018 M4xw
* 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 IANOS_H
#define IANOS_H
#include "../utils/types.h"
typedef enum
{
DRAM_LIB = 0, // DRAM library.
EXEC_ELF = 1, // Executable elf that does not return.
DR64_LIB = 2, // AARCH64 DRAM library.
AR64_ELF = 3, // Executable elf that does not return.
KEEP_IN_RAM = (1 << 31) // Shared library mask.
} elfType_t;
int ianos_loader(bool sdmount, char *path, elfType_t type, void* config);
#endif

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2018 rajkosto
* Copyright (c) 2018 SciresM
*
* 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 <stdlib.h>
#include <string.h>
#include "blz.h"
const blz_footer *blz_get_footer(const unsigned char *compData, unsigned int compDataLen, blz_footer *outFooter)
{
if (compDataLen < sizeof(blz_footer))
return NULL;
const blz_footer *srcFooter = (const blz_footer*)&compData[compDataLen - sizeof(blz_footer)];
if (outFooter != NULL)
memcpy(outFooter, srcFooter, sizeof(blz_footer)); // Must be a memcpy because no umaligned accesses on ARMv4.
return srcFooter;
}
// From https://github.com/SciresM/hactool/blob/master/kip.c which is exactly how kernel does it, thanks SciresM!
int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer)
{
u32 addl_size = footer->addl_size;
u32 header_size = footer->header_size;
u32 cmp_and_hdr_size = footer->cmp_and_hdr_size;
unsigned char* cmp_start = &dataBuf[compSize] - cmp_and_hdr_size;
u32 cmp_ofs = cmp_and_hdr_size - header_size;
u32 out_ofs = cmp_and_hdr_size + addl_size;
while (out_ofs)
{
unsigned char control = cmp_start[--cmp_ofs];
for (unsigned int i=0; i<8; i++)
{
if (control & 0x80)
{
if (cmp_ofs < 2)
return 0; // Out of bounds.
cmp_ofs -= 2;
u16 seg_val = ((unsigned int)(cmp_start[cmp_ofs + 1]) << 8) | cmp_start[cmp_ofs];
u32 seg_size = ((seg_val >> 12) & 0xF) + 3;
u32 seg_ofs = (seg_val & 0x0FFF) + 3;
if (out_ofs < seg_size) // Kernel restricts segment copy to stay in bounds.
seg_size = out_ofs;
out_ofs -= seg_size;
for (unsigned int j = 0; j < seg_size; j++)
cmp_start[out_ofs + j] = cmp_start[out_ofs + j + seg_ofs];
}
else
{
// Copy directly.
if (cmp_ofs < 1)
return 0; //out of bounds
cmp_start[--out_ofs] = cmp_start[--cmp_ofs];
}
control <<= 1;
if (out_ofs == 0) // Blz works backwards, so if it reaches byte 0, it's done.
return 1;
}
}
return 1;
}
int blz_uncompress_srcdest(const unsigned char *compData, unsigned int compDataLen, unsigned char *dstData, unsigned int dstSize)
{
blz_footer footer;
const blz_footer *compFooterPtr = blz_get_footer(compData, compDataLen, &footer);
if (compFooterPtr == NULL)
return 0;
// Decompression must be done in-place, so need to copy the relevant compressed data first.
unsigned int numCompBytes = (const unsigned char*)(compFooterPtr)-compData;
memcpy(dstData, compData, numCompBytes);
memset(&dstData[numCompBytes], 0, dstSize - numCompBytes);
return blz_uncompress_inplace(dstData, compDataLen, &footer);
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2018 rajkosto
*
* 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 _BLZ_H_
#define _BLZ_H_
#include "../../utils/types.h"
typedef struct _blz_footer
{
u32 cmp_and_hdr_size;
u32 header_size;
u32 addl_size;
} blz_footer;
// Returns pointer to footer in compData if present, additionally copies it to outFooter if not NULL.
const blz_footer *blz_get_footer(const unsigned char *compData, unsigned int compDataLen, blz_footer *outFooter);
// Returns 0 on failure.
int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer);
// Returns 0 on failure.
int blz_uncompress_srcdest(const unsigned char *compData, unsigned int compDataLen, unsigned char *dstData, unsigned int dstSize);
#endif

0
ipl/lz.c → bootloader/libs/compr/lz.c Executable file → Normal file
View File

0
ipl/lz.h → bootloader/libs/compr/lz.h Executable file → Normal file
View File

View File

@@ -0,0 +1,589 @@
/* $OpenBSD: exec_elf.h,v 1.53 2014/01/03 03:00:39 guenther Exp $ */
/*
* Copyright (c) 1995, 1996 Erik Theisen. 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/* imported sys/exec_elf.h from OpenBSD */
#ifndef ELF_H
#define ELF_H
#include <stdint.h>
typedef uint8_t Elf_Byte;
typedef uint32_t Elf32_Addr; /* Unsigned program address */
typedef uint32_t Elf32_Off; /* Unsigned file offset */
typedef int32_t Elf32_Sword; /* Signed large integer */
typedef uint32_t Elf32_Word; /* Unsigned large integer */
typedef uint16_t Elf32_Half; /* Unsigned medium integer */
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Off;
typedef int32_t Elf64_Shalf;
#ifdef __alpha__
typedef int64_t Elf64_Sword;
typedef uint64_t Elf64_Word;
#else
typedef int32_t Elf64_Sword;
typedef uint32_t Elf64_Word;
#endif
typedef int64_t Elf64_Sxword;
typedef uint64_t Elf64_Xword;
typedef uint32_t Elf64_Half;
typedef uint16_t Elf64_Quarter;
/*
* e_ident[] identification indexes
* See http://www.sco.com/developers/gabi/latest/ch4.eheader.html
*/
#define EI_MAG0 0 /* file ID */
#define EI_MAG1 1 /* file ID */
#define EI_MAG2 2 /* file ID */
#define EI_MAG3 3 /* file ID */
#define EI_CLASS 4 /* file class */
#define EI_DATA 5 /* data encoding */
#define EI_VERSION 6 /* ELF header version */
#define EI_OSABI 7 /* OS/ABI ID */
#define EI_ABIVERSION 8 /* ABI version */
#define EI_PAD 9 /* start of pad bytes */
#define EI_NIDENT 16 /* Size of e_ident[] */
/* e_ident[] magic number */
#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
#define ELFMAG1 'E' /* e_ident[EI_MAG1] */
#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
#define ELFMAG "\177ELF" /* magic */
#define SELFMAG 4 /* size of magic */
/* e_ident[] file class */
#define ELFCLASSNONE 0 /* invalid */
#define ELFCLASS32 1 /* 32-bit objs */
#define ELFCLASS64 2 /* 64-bit objs */
#define ELFCLASSNUM 3 /* number of classes */
/* e_ident[] data encoding */
#define ELFDATANONE 0 /* invalid */
#define ELFDATA2LSB 1 /* Little-Endian */
#define ELFDATA2MSB 2 /* Big-Endian */
#define ELFDATANUM 3 /* number of data encode defines */
/* e_ident[] Operating System/ABI */
#define ELFOSABI_SYSV 0 /* UNIX System V ABI */
#define ELFOSABI_HPUX 1 /* HP-UX operating system */
#define ELFOSABI_NETBSD 2 /* NetBSD */
#define ELFOSABI_LINUX 3 /* GNU/Linux */
#define ELFOSABI_HURD 4 /* GNU/Hurd */
#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
#define ELFOSABI_SOLARIS 6 /* Solaris */
#define ELFOSABI_MONTEREY 7 /* Monterey */
#define ELFOSABI_IRIX 8 /* IRIX */
#define ELFOSABI_FREEBSD 9 /* FreeBSD */
#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
#define ELFOSABI_MODESTO 11 /* Novell Modesto */
#define ELFOSABI_OPENBSD 12 /* OpenBSD */
#define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
/* e_ident */
#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
(ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
(ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
(ehdr).e_ident[EI_MAG3] == ELFMAG3)
/* ELF Header */
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* ELF Identification */
Elf32_Half e_type; /* object file type */
Elf32_Half e_machine; /* machine */
Elf32_Word e_version; /* object file version */
Elf32_Addr e_entry; /* virtual entry point */
Elf32_Off e_phoff; /* program header table offset */
Elf32_Off e_shoff; /* section header table offset */
Elf32_Word e_flags; /* processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size */
Elf32_Half e_phentsize; /* program header entry size */
Elf32_Half e_phnum; /* number of program header entries */
Elf32_Half e_shentsize; /* section header entry size */
Elf32_Half e_shnum; /* number of section header entries */
Elf32_Half e_shstrndx; /* section header table's "section
header string table" entry offset */
} Elf32_Ehdr;
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Id bytes */
Elf64_Quarter e_type; /* file type */
Elf64_Quarter e_machine; /* machine type */
Elf64_Half e_version; /* version number */
Elf64_Addr e_entry; /* entry point */
Elf64_Off e_phoff; /* Program hdr offset */
Elf64_Off e_shoff; /* Section hdr offset */
Elf64_Half e_flags; /* Processor flags */
Elf64_Quarter e_ehsize; /* sizeof ehdr */
Elf64_Quarter e_phentsize; /* Program header entry size */
Elf64_Quarter e_phnum; /* Number of program headers */
Elf64_Quarter e_shentsize; /* Section header entry size */
Elf64_Quarter e_shnum; /* Number of section headers */
Elf64_Quarter e_shstrndx; /* String table index */
} Elf64_Ehdr;
/* e_type */
#define ET_NONE 0 /* No file type */
#define ET_REL 1 /* relocatable file */
#define ET_EXEC 2 /* executable file */
#define ET_DYN 3 /* shared object file */
#define ET_CORE 4 /* core file */
#define ET_NUM 5 /* number of types */
#define ET_LOPROC 0xff00 /* reserved range for processor */
#define ET_HIPROC 0xffff /* specific e_type */
/* e_machine */
#define EM_NONE 0 /* No Machine */
#define EM_M32 1 /* AT&T WE 32100 */
#define EM_SPARC 2 /* SPARC */
#define EM_386 3 /* Intel 80386 */
#define EM_68K 4 /* Motorola 68000 */
#define EM_88K 5 /* Motorola 88000 */
#define EM_486 6 /* Intel 80486 - unused? */
#define EM_860 7 /* Intel 80860 */
#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */
/*
* Don't know if EM_MIPS_RS4_BE,
* EM_SPARC64, EM_PARISC,
* or EM_PPC are ABI compliant
*/
#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
#define EM_SPARC64 11 /* SPARC v9 64-bit unofficial */
#define EM_PARISC 15 /* HPPA */
#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
#define EM_PPC 20 /* PowerPC */
#define EM_ARM 40 /* ARM AArch32 */
#define EM_ALPHA 41 /* DEC ALPHA */
#define EM_SH 42 /* Hitachi/Renesas Super-H */
#define EM_SPARCV9 43 /* SPARC version 9 */
#define EM_IA_64 50 /* Intel IA-64 Processor */
#define EM_AMD64 62 /* AMD64 architecture */
#define EM_VAX 75 /* DEC VAX */
#define EM_AARCH64 183 /* ARM AArch64 */
/* Non-standard */
#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */
/* Version */
#define EV_NONE 0 /* Invalid */
#define EV_CURRENT 1 /* Current */
#define EV_NUM 2 /* number of versions */
/* Section Header */
typedef struct
{
Elf32_Word sh_name; /* name - index into section header
* string table section */
Elf32_Word sh_type; /* type */
Elf32_Word sh_flags; /* flags */
Elf32_Addr sh_addr; /* address */
Elf32_Off sh_offset; /* file offset */
Elf32_Word sh_size; /* section size */
Elf32_Word sh_link; /* section header table index link */
Elf32_Word sh_info; /* extra information */
Elf32_Word sh_addralign; /* address alignment */
Elf32_Word sh_entsize; /* section entry size */
} Elf32_Shdr;
typedef struct
{
Elf64_Half sh_name; /* section name */
Elf64_Half sh_type; /* section type */
Elf64_Xword sh_flags; /* section flags */
Elf64_Addr sh_addr; /* virtual address */
Elf64_Off sh_offset; /* file offset */
Elf64_Xword sh_size; /* section size */
Elf64_Half sh_link; /* link to another */
Elf64_Half sh_info; /* misc info */
Elf64_Xword sh_addralign; /* memory alignment */
Elf64_Xword sh_entsize; /* table entry size */
} Elf64_Shdr;
/* Special Section Indexes */
#define SHN_UNDEF 0 /* undefined */
#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */
#define SHN_LOPROC 0xff00 /* reserved range for processor */
#define SHN_HIPROC 0xff1f /* specific section indexes */
#define SHN_ABS 0xfff1 /* absolute value */
#define SHN_COMMON 0xfff2 /* common symbol */
#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */
/* sh_type */
#define SHT_NULL 0 /* inactive */
#define SHT_PROGBITS 1 /* program defined information */
#define SHT_SYMTAB 2 /* symbol table section */
#define SHT_STRTAB 3 /* string table section */
#define SHT_RELA 4 /* relocation section with addends*/
#define SHT_HASH 5 /* symbol hash table section */
#define SHT_DYNAMIC 6 /* dynamic section */
#define SHT_NOTE 7 /* note section */
#define SHT_NOBITS 8 /* no space section */
#define SHT_REL 9 /* relation section without addends */
#define SHT_SHLIB 10 /* reserved - purpose unknown */
#define SHT_DYNSYM 11 /* dynamic symbol table section */
#define SHT_NUM 12 /* number of section types */
#define SHT_LOPROC 0x70000000 /* reserved range for processor */
#define SHT_HIPROC 0x7fffffff /* specific section header types */
#define SHT_LOUSER 0x80000000 /* reserved range for application */
#define SHT_HIUSER 0xffffffff /* specific indexes */
/* Section names */
#define ELF_BSS ".bss" /* uninitialized data */
#define ELF_DATA ".data" /* initialized data */
#define ELF_DEBUG ".debug" /* debug */
#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */
#define ELF_DYNSTR ".dynstr" /* dynamic string table */
#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */
#define ELF_FINI ".fini" /* termination code */
#define ELF_GOT ".got" /* global offset table */
#define ELF_HASH ".hash" /* symbol hash table */
#define ELF_INIT ".init" /* initialization code */
#define ELF_REL_DATA ".rel.data" /* relocation data */
#define ELF_REL_FINI ".rel.fini" /* relocation termination code */
#define ELF_REL_INIT ".rel.init" /* relocation initialization code */
#define ELF_REL_DYN ".rel.dyn" /* relocation dynamic link info */
#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */
#define ELF_REL_TEXT ".rel.text" /* relocation code */
#define ELF_RODATA ".rodata" /* read-only data */
#define ELF_SHSTRTAB ".shstrtab" /* section header string table */
#define ELF_STRTAB ".strtab" /* string table */
#define ELF_SYMTAB ".symtab" /* symbol table */
#define ELF_TEXT ".text" /* code */
/* Section Attribute Flags - sh_flags */
#define SHF_WRITE 0x1 /* Writable */
#define SHF_ALLOC 0x2 /* occupies memory */
#define SHF_EXECINSTR 0x4 /* executable */
#define SHF_TLS 0x400 /* thread local storage */
#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor \
* specific section attributes */
/* Symbol Table Entry */
typedef struct elf32_sym
{
Elf32_Word st_name; /* name - index into string table */
Elf32_Addr st_value; /* symbol value */
Elf32_Word st_size; /* symbol size */
unsigned char st_info; /* type and binding */
unsigned char st_other; /* 0 - no defined meaning */
Elf32_Half st_shndx; /* section header index */
} Elf32_Sym;
typedef struct
{
Elf64_Half st_name; /* Symbol name index in str table */
Elf_Byte st_info; /* type / binding attrs */
Elf_Byte st_other; /* unused */
Elf64_Quarter st_shndx; /* section index of symbol */
Elf64_Xword st_value; /* value of symbol */
Elf64_Xword st_size; /* size of symbol */
} Elf64_Sym;
/* Symbol table index */
#define STN_UNDEF 0 /* undefined */
/* Extract symbol info - st_info */
#define ELF32_ST_BIND(x) ((x) >> 4)
#define ELF32_ST_TYPE(x) (((unsigned int)x) & 0xf)
#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t)&0xf))
#define ELF64_ST_BIND(x) ((x) >> 4)
#define ELF64_ST_TYPE(x) (((unsigned int)x) & 0xf)
#define ELF64_ST_INFO(b, t) (((b) << 4) + ((t)&0xf))
/* Symbol Binding - ELF32_ST_BIND - st_info */
#define STB_LOCAL 0 /* Local symbol */
#define STB_GLOBAL 1 /* Global symbol */
#define STB_WEAK 2 /* like global - lower precedence */
#define STB_NUM 3 /* number of symbol bindings */
#define STB_LOPROC 13 /* reserved range for processor */
#define STB_HIPROC 15 /* specific symbol bindings */
/* Symbol type - ELF32_ST_TYPE - st_info */
#define STT_NOTYPE 0 /* not specified */
#define STT_OBJECT 1 /* data object */
#define STT_FUNC 2 /* function */
#define STT_SECTION 3 /* section */
#define STT_FILE 4 /* file */
#define STT_TLS 6 /* thread local storage */
#define STT_LOPROC 13 /* reserved range for processor */
#define STT_HIPROC 15 /* specific symbol types */
/* Relocation entry with implicit addend */
typedef struct
{
Elf32_Addr r_offset; /* offset of relocation */
Elf32_Word r_info; /* symbol table index and type */
} Elf32_Rel;
/* Relocation entry with explicit addend */
typedef struct
{
Elf32_Addr r_offset; /* offset of relocation */
Elf32_Word r_info; /* symbol table index and type */
Elf32_Sword r_addend;
} Elf32_Rela;
/* Extract relocation info - r_info */
#define ELF32_R_SYM(i) ((i) >> 8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
typedef struct
{
Elf64_Xword r_offset; /* where to do it */
Elf64_Xword r_info; /* index & type of relocation */
} Elf64_Rel;
typedef struct
{
Elf64_Xword r_offset; /* where to do it */
Elf64_Xword r_info; /* index & type of relocation */
Elf64_Sxword r_addend; /* adjustment value */
} Elf64_Rela;
#define ELF64_R_SYM(info) ((info) >> 32)
#define ELF64_R_TYPE(info) ((info)&0xFFFFFFFF)
#define ELF64_R_INFO(s, t) (((s) << 32) + (__uint32_t)(t))
#if defined(__mips64__) && defined(__MIPSEL__)
/*
* The 64-bit MIPS ELF ABI uses a slightly different relocation format
* than the regular ELF ABI: the r_info field is split into several
* pieces (see gnu/usr.bin/binutils/include/elf/mips.h for details).
*/
#undef ELF64_R_SYM
#undef ELF64_R_TYPE
#undef ELF64_R_INFO
#define ELF64_R_TYPE(info) (swap32((info) >> 32))
#define ELF64_R_SYM(info) ((info)&0xFFFFFFFF)
#define ELF64_R_INFO(s, t) (((__uint64_t)swap32(t) << 32) + (__uint32_t)(s))
#endif /* __mips64__ && __MIPSEL__ */
/* Program Header */
typedef struct
{
Elf32_Word p_type; /* segment type */
Elf32_Off p_offset; /* segment offset */
Elf32_Addr p_vaddr; /* virtual address of segment */
Elf32_Addr p_paddr; /* physical address - ignored? */
Elf32_Word p_filesz; /* number of bytes in file for seg. */
Elf32_Word p_memsz; /* number of bytes in mem. for seg. */
Elf32_Word p_flags; /* flags */
Elf32_Word p_align; /* memory alignment */
} Elf32_Phdr;
typedef struct
{
Elf64_Half p_type; /* entry type */
Elf64_Half p_flags; /* flags */
Elf64_Off p_offset; /* offset */
Elf64_Addr p_vaddr; /* virtual address */
Elf64_Addr p_paddr; /* physical address */
Elf64_Xword p_filesz; /* file size */
Elf64_Xword p_memsz; /* memory size */
Elf64_Xword p_align; /* memory & file alignment */
} Elf64_Phdr;
/* Segment types - p_type */
#define PT_NULL 0 /* unused */
#define PT_LOAD 1 /* loadable segment */
#define PT_DYNAMIC 2 /* dynamic linking section */
#define PT_INTERP 3 /* the RTLD */
#define PT_NOTE 4 /* auxiliary information */
#define PT_SHLIB 5 /* reserved - purpose undefined */
#define PT_PHDR 6 /* program header */
#define PT_TLS 7 /* thread local storage */
#define PT_LOOS 0x60000000 /* reserved range for OS */
#define PT_HIOS 0x6fffffff /* specific segment types */
#define PT_LOPROC 0x70000000 /* reserved range for processor */
#define PT_HIPROC 0x7fffffff /* specific segment types */
#define PT_OPENBSD_RANDOMIZE 0x65a3dbe6 /* fill with random data */
#define PT_GANDR_KERNEL 0x67646b6c /* gdkl */
/* Segment flags - p_flags */
#define PF_X 0x1 /* Executable */
#define PF_W 0x2 /* Writable */
#define PF_R 0x4 /* Readable */
#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */
/* specific segment flags */
/* Dynamic structure */
typedef struct
{
Elf32_Sword d_tag; /* controls meaning of d_val */
union {
Elf32_Word d_val; /* Multiple meanings - see d_tag */
Elf32_Addr d_ptr; /* program virtual address */
} d_un;
} Elf32_Dyn;
typedef struct
{
Elf64_Xword d_tag; /* controls meaning of d_val */
union {
Elf64_Addr d_ptr;
Elf64_Xword d_val;
} d_un;
} Elf64_Dyn;
/* Dynamic Array Tags - d_tag */
#define DT_NULL 0 /* marks end of _DYNAMIC array */
#define DT_NEEDED 1 /* string table offset of needed lib */
#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */
#define DT_PLTGOT 3 /* address PLT/GOT */
#define DT_HASH 4 /* address of symbol hash table */
#define DT_STRTAB 5 /* address of string table */
#define DT_SYMTAB 6 /* address of symbol table */
#define DT_RELA 7 /* address of relocation table */
#define DT_RELASZ 8 /* size of relocation table */
#define DT_RELAENT 9 /* size of relocation entry */
#define DT_STRSZ 10 /* size of string table */
#define DT_SYMENT 11 /* size of symbol table entry */
#define DT_INIT 12 /* address of initialization func. */
#define DT_FINI 13 /* address of termination function */
#define DT_SONAME 14 /* string table offset of shared obj */
#define DT_RPATH 15 /* string table offset of library \
* search path */
#define DT_SYMBOLIC 16 /* start sym search in shared obj. */
#define DT_REL 17 /* address of rel. tbl. w addends */
#define DT_RELSZ 18 /* size of DT_REL relocation table */
#define DT_RELENT 19 /* size of DT_REL relocation entry */
#define DT_PLTREL 20 /* PLT referenced relocation entry */
#define DT_DEBUG 21 /* bugger */
#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */
#define DT_JMPREL 23 /* add. of PLT's relocation entries */
#define DT_BIND_NOW 24 /* Bind now regardless of env setting */
#define DT_LOOS 0x6000000d /* reserved range for OS */
#define DT_HIOS 0x6ffff000 /* specific dynamic array tags */
#define DT_LOPROC 0x70000000 /* reserved range for processor */
#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */
/* some other useful tags */
#define DT_RELACOUNT 0x6ffffff9 /* if present, number of RELATIVE */
#define DT_RELCOUNT 0x6ffffffa /* relocs, which must come first */
#define DT_FLAGS_1 0x6ffffffb
/* Dynamic Flags - DT_FLAGS_1 .dynamic entry */
#define DF_1_NOW 0x00000001
#define DF_1_GLOBAL 0x00000002
#define DF_1_GROUP 0x00000004
#define DF_1_NODELETE 0x00000008
#define DF_1_LOADFLTR 0x00000010
#define DF_1_INITFIRST 0x00000020
#define DF_1_NOOPEN 0x00000040
#define DF_1_ORIGIN 0x00000080
#define DF_1_DIRECT 0x00000100
#define DF_1_TRANS 0x00000200
#define DF_1_INTERPOSE 0x00000400
#define DF_1_NODEFLIB 0x00000800
#define DF_1_NODUMP 0x00001000
#define DF_1_CONLFAT 0x00002000
/* ld.so: number of low tags that are used saved internally (0 .. DT_NUM-1) */
#define DT_NUM (DT_JMPREL + 1)
/*
* Note Definitions
*/
typedef struct
{
Elf32_Word namesz;
Elf32_Word descsz;
Elf32_Word type;
} Elf32_Note;
typedef struct
{
Elf64_Half namesz;
Elf64_Half descsz;
Elf64_Half type;
} Elf64_Note;
#if defined(ELFSIZE) && (ELFSIZE == 32)
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Phdr Elf32_Phdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Rel Elf32_Rel
#define Elf_RelA Elf32_Rela
#define Elf_Dyn Elf32_Dyn
#define Elf_Half Elf32_Half
#define Elf_Word Elf32_Word
#define Elf_Sword Elf32_Sword
#define Elf_Addr Elf32_Addr
#define Elf_Off Elf32_Off
#define Elf_Nhdr Elf32_Nhdr
#define Elf_Note Elf32_Note
#define ELF_R_SYM ELF32_R_SYM
#define ELF_R_TYPE ELF32_R_TYPE
#define ELF_R_INFO ELF32_R_INFO
#define ELFCLASS ELFCLASS32
#define ELF_ST_BIND ELF32_ST_BIND
#define ELF_ST_TYPE ELF32_ST_TYPE
#define ELF_ST_INFO ELF32_ST_INFO
#elif defined(ELFSIZE) && (ELFSIZE == 64)
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Phdr Elf64_Phdr
#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
#define Elf_Rel Elf64_Rel
#define Elf_RelA Elf64_Rela
#define Elf_Dyn Elf64_Dyn
#define Elf_Half Elf64_Half
#define Elf_Word Elf64_Word
#define Elf_Sword Elf64_Sword
#define Elf_Addr Elf64_Addr
#define Elf_Off Elf64_Off
#define Elf_Nhdr Elf64_Nhdr
#define Elf_Note Elf64_Note
#define ELF_R_SYM ELF64_R_SYM
#define ELF_R_TYPE ELF64_R_TYPE
#define ELF_R_INFO ELF64_R_INFO
#define ELFCLASS ELFCLASS64
#define ELF_ST_BIND ELF64_ST_BIND
#define ELF_ST_TYPE ELF64_ST_TYPE
#define ELF_ST_INFO ELF64_ST_INFO
#endif
#endif

View File

@@ -0,0 +1,49 @@
/*
* Copyright © 2014, Owen Shepherd
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef ELFARCH_H
#define ELFARCH_H
#if defined(__i386__)
#define EM_THIS EM_386
#define EL_ARCH_USES_REL
#elif defined(__amd64__)
#define EM_THIS EM_AMD64
#define EL_ARCH_USES_RELA
#elif defined(__arm__)
#define EM_THIS EM_ARM
#define EL_ARCH_USES_REL
#elif defined(__aarch64__)
#define EM_THIS EM_AARCH64
#define EL_ARCH_USES_RELA
#define EL_ARCH_USES_REL
#else
#error specify your ELF architecture
#endif
#if defined(__LP64__) || defined(__LLP64__)
#define ELFSIZE 64
#else
#define ELFSIZE 32
#endif
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define ELFDATATHIS ELFDATA2LSB
#else
#define ELFDATATHIS ELFDATA2MSB
#endif
#endif

View File

@@ -0,0 +1,324 @@
/*
* Copyright © 2018, M4xw
* Copyright © 2014, Owen Shepherd
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <string.h>
#include "elfload.h"
el_status el_pread(el_ctx *ctx, void *def, size_t nb, size_t offset)
{
return ctx->pread(ctx, def, nb, offset) ? EL_OK : EL_EIO;
}
#define EL_PHOFF(ctx, num) (((ctx)->ehdr.e_phoff + (num) *(ctx)->ehdr.e_phentsize))
el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, uint32_t type, unsigned *i)
{
el_status rv = EL_OK;
for (; *i < ctx->ehdr.e_phnum; (*i)++)
{
if ((rv = el_pread(ctx, phdr, sizeof *phdr, EL_PHOFF(ctx, *i))))
return rv;
if (phdr->p_type == type)
{
return rv;
}
}
*i = -1;
return rv;
}
#define EL_SHOFF(ctx, num) (((ctx)->ehdr.e_shoff + (num) *(ctx)->ehdr.e_shentsize))
el_status el_findshdr(el_ctx *ctx, Elf_Shdr *shdr, uint32_t type, unsigned *i)
{
el_status rv = EL_OK;
for (; *i < ctx->ehdr.e_shnum; (*i)++)
{
if ((rv = el_pread(ctx, shdr, sizeof *shdr, EL_SHOFF(ctx, *i))))
return rv;
if (shdr->sh_type == type)
{
return rv;
}
}
*i = -1;
return rv;
}
el_status el_init(el_ctx *ctx)
{
el_status rv = EL_OK;
if ((rv = el_pread(ctx, &ctx->ehdr, sizeof ctx->ehdr, 0)))
return rv;
/* validate header */
if (!IS_ELF(ctx->ehdr))
return EL_NOTELF;
if (ctx->ehdr.e_ident[EI_CLASS] != ELFCLASS)
return EL_WRONGBITS;
if (ctx->ehdr.e_ident[EI_DATA] != ELFDATATHIS)
return EL_WRONGENDIAN;
if (ctx->ehdr.e_ident[EI_VERSION] != EV_CURRENT)
return EL_NOTELF;
if (ctx->ehdr.e_type != ET_EXEC && ctx->ehdr.e_type != ET_DYN)
return EL_NOTEXEC;
if (ctx->ehdr.e_machine != EM_THIS)
return EL_WRONGARCH;
if (ctx->ehdr.e_version != EV_CURRENT)
return EL_NOTELF;
/* load phdrs */
Elf_Phdr ph;
/* iterate through, calculate extents */
ctx->base_load_paddr = ctx->base_load_vaddr = 0;
ctx->align = 1;
ctx->memsz = 0;
unsigned i = 0;
for (;;)
{
if ((rv = el_findphdr(ctx, &ph, PT_LOAD, &i)))
return rv;
if (i == (unsigned)-1)
break;
Elf_Addr phend = ph.p_vaddr + ph.p_memsz;
if (phend > ctx->memsz)
ctx->memsz = phend;
if (ph.p_align > ctx->align)
ctx->align = ph.p_align;
i++;
}
// Program Header
if (ctx->ehdr.e_type == ET_DYN)
{
i = 0;
if ((rv = el_findphdr(ctx, &ph, PT_DYNAMIC, &i)))
return rv;
if (i == (unsigned)-1)
return EL_NODYN;
ctx->dynoff = ph.p_offset;
ctx->dynsize = ph.p_filesz;
}
else
{
ctx->dynoff = 0;
ctx->dynsize = 0;
}
// Section String Table
if (ctx->ehdr.e_type == ET_DYN)
{
i = ctx->ehdr.e_shstrndx - 1;
if ((rv = el_findshdr(ctx, &ctx->shstr, SHT_STRTAB, &i)))
return rv;
// Reset
i = 0;
if ((rv = el_findshdr(ctx, &ctx->symtab, SHT_SYMTAB, &i)))
return rv;
if (i == (unsigned)-1)
return EL_NODYN;
}
return rv;
}
/*
typedef void* (*el_alloc_cb)(
el_ctx *ctx,
Elf_Addr phys,
Elf_Addr virt,
Elf_Addr size);
*/
el_status el_load(el_ctx *ctx, el_alloc_cb alloc)
{
el_status rv = EL_OK;
/* address deltas */
Elf_Addr pdelta = ctx->base_load_paddr;
Elf_Addr vdelta = ctx->base_load_vaddr;
/* iterate paddrs */
Elf_Phdr ph;
unsigned i = 0;
for (;;)
{
if ((rv = el_findphdr(ctx, &ph, PT_LOAD, &i)))
return rv;
if (i == (unsigned)-1)
break;
Elf_Addr pload = ph.p_paddr + pdelta;
Elf_Addr vload = ph.p_vaddr + vdelta;
/* allocate mem */
char *dest = alloc(ctx, pload, vload, ph.p_memsz);
if (!dest)
return EL_ENOMEM;
EL_DEBUG("Loading seg fileoff %x, vaddr %x to %p\n",
ph.p_offset, ph.p_vaddr, dest);
/* read loaded portion */
if ((rv = el_pread(ctx, dest, ph.p_filesz, ph.p_offset)))
return rv;
/* zero mem-only portion */
memset(dest + ph.p_filesz, 0, ph.p_memsz - ph.p_filesz);
i++;
}
return rv;
}
el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t tag)
{
el_status rv = EL_OK;
size_t ndyn = ctx->dynsize / sizeof(Elf_Dyn);
for (unsigned i = 0; i < ndyn; i++)
{
if ((rv = el_pread(ctx, dyn, sizeof *dyn, ctx->dynoff + i * sizeof *dyn)))
return rv;
if (dyn->d_tag == tag)
return EL_OK;
}
dyn->d_tag = DT_NULL;
return EL_OK;
}
el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, uint32_t type)
{
el_status rv = EL_OK;
Elf_Dyn rel, relsz, relent;
if ((rv = el_finddyn(ctx, &rel, type)))
return rv;
if ((rv = el_finddyn(ctx, &relsz, type + 1)))
return rv;
if ((rv = el_finddyn(ctx, &relent, type + 2)))
return rv;
if (rel.d_tag == DT_NULL || relsz.d_tag == DT_NULL || relent.d_tag == DT_NULL)
{
ri->entrysize = 0;
ri->tablesize = 0;
ri->tableoff = 0;
}
else
{
ri->tableoff = rel.d_un.d_ptr;
ri->tablesize = relsz.d_un.d_val;
ri->entrysize = relent.d_un.d_val;
}
return rv;
}
extern el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel);
extern el_status el_applyrela(el_ctx *ctx, Elf_RelA *rela);
el_status el_relocate(el_ctx *ctx)
{
el_status rv = EL_OK;
// not dynamic
if (ctx->ehdr.e_type != ET_DYN)
return EL_OK;
char *base = (char *)ctx->base_load_paddr;
el_relocinfo ri;
#ifdef EL_ARCH_USES_REL
if ((rv = el_findrelocs(ctx, &ri, DT_REL)))
return rv;
if (ri.entrysize != sizeof(Elf_Rel) && ri.tablesize)
{
EL_DEBUG("Relocation size %u doesn't match expected %u\n",
ri.entrysize, sizeof(Elf_Rel));
return EL_BADREL;
}
size_t relcnt = ri.tablesize / sizeof(Elf_Rel);
Elf_Rel *reltab = (Elf_Rel *)(base + ri.tableoff);
for (size_t i = 0; i < relcnt; i++)
{
if ((rv = el_applyrel(ctx, &reltab[i])))
return rv;
}
#endif
#ifdef EL_ARCH_USES_RELA
if ((rv = el_findrelocs(ctx, &ri, DT_RELA)))
return rv;
if (ri.entrysize != sizeof(Elf_RelA) && ri.tablesize)
{
EL_DEBUG("Relocation size %u doesn't match expected %u\n",
ri.entrysize, sizeof(Elf_RelA));
return EL_BADREL;
}
size_t relacnt = ri.tablesize / sizeof(Elf_RelA);
Elf_RelA *relatab = (Elf_RelA *)(base + ri.tableoff);
for (size_t i = 0; i < relacnt; i++)
{
if ((rv = el_applyrela(ctx, &relatab[i])))
return rv;
}
#endif
#if !defined(EL_ARCH_USES_REL) && !defined(EL_ARCH_USES_RELA)
#error No relocation type defined!
#endif
return rv;
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright © 2018, M4xw
* Copyright © 2014, Owen Shepherd
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef ELFLOAD_H
#define ELFLOAD_H
#include <stddef.h>
#include "elfarch.h"
#include "elf.h"
#include "../../utils/types.h"
#ifdef DEBUG
#include "../../gfx/gfx.h"
extern gfx_con_t gfx_con;
#define EL_DEBUG(format, ...) \
gfx_printf(&gfx_con, format __VA_OPT__(, ) __VA_ARGS__)
#else
#define EL_DEBUG(...) \
do \
{ \
} while (0)
#endif
typedef enum
{
EL_OK = 0,
EL_EIO,
EL_ENOMEM,
EL_NOTELF,
EL_WRONGBITS,
EL_WRONGENDIAN,
EL_WRONGARCH,
EL_WRONGOS,
EL_NOTEXEC,
EL_NODYN,
EL_BADREL,
} el_status;
typedef struct el_ctx
{
bool (*pread)(struct el_ctx *ctx, void *dest, size_t nb, size_t offset);
/* base_load_* -> address we are actually going to load at
*/
Elf_Addr
base_load_paddr,
base_load_vaddr;
/* size in memory of binary */
Elf_Addr memsz;
/* required alignment */
Elf_Addr align;
/* ELF header */
Elf_Ehdr ehdr;
// Section Header Str Table
Elf_Shdr shstr;
Elf_Shdr symtab;
/* Offset of dynamic table (0 if not ET_DYN) */
Elf_Off dynoff;
/* Size of dynamic table (0 if not ET_DYN) */
Elf_Addr dynsize;
} el_ctx;
el_status el_pread(el_ctx *ctx, void *def, size_t nb, size_t offset);
el_status el_init(el_ctx *ctx);
typedef void *(*el_alloc_cb)(
el_ctx *ctx,
Elf_Addr phys,
Elf_Addr virt,
Elf_Addr size);
el_status el_load(el_ctx *ctx, el_alloc_cb alloccb);
/* find the next phdr of type \p type, starting at \p *i.
* On success, returns EL_OK with *i set to the phdr number, and the phdr loaded
* in *phdr.
*
* If the end of the phdrs table was reached, *i is set to -1 and the contents
* of *phdr are undefined
*/
el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, uint32_t type, unsigned *i);
/* Relocate the loaded executable */
el_status el_relocate(el_ctx *ctx);
/* find a dynamic table entry
* returns the entry on success, dyn->d_tag = DT_NULL on failure
*/
el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t type);
typedef struct
{
Elf_Off tableoff;
Elf_Addr tablesize;
Elf_Addr entrysize;
} el_relocinfo;
/* find all information regarding relocations of a specific type.
*
* pass DT_REL or DT_RELA for type
* sets ri->entrysize = 0 if not found
*/
el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, uint32_t type);
#endif

View File

@@ -0,0 +1,84 @@
/*
* Copyright © 2014, Owen Shepherd
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "elfload.h"
#if defined(__aarch64__)
#define R_AARCH64_NONE 0
#define R_AARCH64_RELATIVE 1027
el_status el_applyrela(el_ctx *ctx, Elf_RelA *rel)
{
uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr);
uint32_t type = ELF_R_TYPE(rel->r_info);
uint32_t sym = ELF_R_SYM(rel->r_info);
switch (type)
{
case R_AARCH64_NONE:
EL_DEBUG("R_AARCH64_NONE\n");
break;
case R_AARCH64_RELATIVE:
if (sym)
{
EL_DEBUG("R_AARCH64_RELATIVE with symbol ref!\n");
return EL_BADREL;
}
EL_DEBUG("Applying R_AARCH64_RELATIVE reloc @%p\n", p);
*p = rel->r_addend + ctx->base_load_vaddr;
break;
default:
EL_DEBUG("Bad relocation %u\n", type);
return EL_BADREL;
}
return EL_OK;
}
el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel)
{
uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr);
uint32_t type = ELF_R_TYPE(rel->r_info);
uint32_t sym = ELF_R_SYM(rel->r_info);
switch (type)
{
case R_AARCH64_NONE:
EL_DEBUG("R_AARCH64_NONE\n");
break;
case R_AARCH64_RELATIVE:
if (sym)
{
EL_DEBUG("R_AARCH64_RELATIVE with symbol ref!\n");
return EL_BADREL;
}
EL_DEBUG("Applying R_AARCH64_RELATIVE reloc @%p\n", p);
*p += ctx->base_load_vaddr;
break;
default:
EL_DEBUG("Bad relocation %u\n", type);
return EL_BADREL;
}
return EL_OK;
}
#endif

View File

@@ -0,0 +1,66 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <m4x@m4xw.net> wrote this file. As long as you retain this notice you can do
* whatever you want with this stuff. If we meet some day, and you think this
* stuff is worth it, you can buy me a beer in return. M4xw
* ----------------------------------------------------------------------------
*/
#include "elfload.h"
#if defined(__arm__)
// Taken from http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044f/IHI0044F_aaelf.pdf
#define R_ARM_NONE 0
#define R_ARM_ABS32 2
#define R_ARM_JUMP_SLOT 22
#define R_ARM_GLOB_DAT 21
#define R_ARM_RELATIVE 23
el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel)
{
uint32_t sym = ELF_R_SYM(rel->r_info); // Symbol offset
uint32_t type = ELF_R_TYPE(rel->r_info); // Relocation Type
uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr); // Target Addr
#if 0 // For later symbol usage
Elf32_Sym *elfSym;
const char *symbolName;
// We resolve relocs from the originating elf-image
elfSym = (Elf32_Sym *)(ctx->symtab.sh_offset + (char *)buffteg) + sym;
int strtab_offset = ctx->shstr.sh_offset;
char *strtab = (char *)buffteg + strtab_offset;
symbolName = strtab + elfSym->st_name;
//EL_DEBUG("Str: %s sz: %x val: %x\n", symbolName, elfSym->st_size, elfSym->st_value);
#endif
switch (type)
{
case R_ARM_NONE:
EL_DEBUG("R_ARM_NONE\n");
break;
case R_ARM_JUMP_SLOT:
case R_ARM_ABS32:
case R_ARM_GLOB_DAT:
// Stubbed for later purpose
//*p += elfSym->st_value; // + vaddr from sec
//*p |= 0; // 1 if Thumb && STT_FUNC, ignored for now
break;
case R_ARM_RELATIVE: // Needed for PIE
if (sym)
{
return EL_BADREL;
}
*p += ctx->base_load_vaddr;
break;
default:
return EL_BADREL;
}
return EL_OK;
}
#endif

2
ipl/diskio.c → bootloader/libs/fatfs/diskio.c Executable file → Normal file
View File

@@ -9,7 +9,7 @@
#include <string.h>
#include "diskio.h" /* FatFs lower layer API */
#include "sdmmc.h"
#include "../../storage/sdmmc.h"
extern sdmmc_storage_t sd_storage;

2
ipl/diskio.h → bootloader/libs/fatfs/diskio.h Executable file → Normal file
View File

@@ -9,7 +9,7 @@
extern "C" {
#endif
#include "integer.h"
#include "../../utils/types.h"
/* Status of Disk Functions */

64
ipl/ff.c → bootloader/libs/fatfs/ff.c Executable file → Normal file
View File

@@ -24,10 +24,10 @@
#include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of device I/O functions */
#include "gfx.h"
#include "../../gfx/gfx.h"
extern gfx_ctxt_t gfx_ctxt;
extern gfx_con_t gfx_con;
#define EFSPRINTF(text, ...) print_error(); gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);\
#define EFSPRINTF(text, ...) print_error(); gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
//#define EFSPRINTF(...)
/*--------------------------------------------------------------------------
@@ -3248,7 +3248,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
stat = disk_status(fs->pdrv);
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */
EFSPRINTF("Write protected!");
EFSPRINTF("WPEN1");
return FR_WRITE_PROTECTED;
}
return FR_OK; /* The filesystem object is valid */
@@ -3262,11 +3262,11 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */
EFSPRINTF("Medium not ready or hard error!");
EFSPRINTF("MDNR");
return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
}
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
EFSPRINTF("Write protected!");
EFSPRINTF("WPEN2");
return FR_WRITE_PROTECTED;
}
#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */
@@ -3290,11 +3290,11 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
} while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4);
}
if (fmt == 4) {
EFSPRINTF("Could not load boot record!");
EFSPRINTF("BRNL");
return FR_DISK_ERR; /* An error occured in the disk I/O layer */
}
if (fmt >= 2) {
EFSPRINTF("No FAT/FAT32/exFAT found!");
EFSPRINTF("NOFAT");
return FR_NO_FILESYSTEM; /* No FAT volume is found */
}
@@ -3312,7 +3312,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */
if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */
EFSPRINTF("exFAT - Sector size does not match physical sector size!");
EFSPRINTF("EXSPS");
return FR_NO_FILESYSTEM;
}
@@ -3324,13 +3324,12 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */
if (fs->n_fats != 1) {
EFSPRINTF("exFAT - Multiple or no file allocation tables found!");
EFSPRINTF("EXFNF");
return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */
}
fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */
if (fs->csize == 0) {
EFSPRINTF("exFAT - Sectors per clusters!");
return FR_NO_FILESYSTEM; /* (Must be 1..32768) */
}
@@ -3349,14 +3348,14 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
/* Check if bitmap location is in assumption (at the first cluster) */
if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) {
EFSPRINTF("exFAT - Bitmap location not at 1st cluster!");
EFSPRINTF("EXBM1C");
return FR_DISK_ERR;
}
for (i = 0; i < SS(fs); i += SZDIRE) {
if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */
}
if (i == SS(fs)) {
EFSPRINTF("exFAT - Bitmap allocation is missing!");
EFSPRINTF("EXBMM");
return FR_NO_FILESYSTEM;
}
#if !FF_FS_READONLY
@@ -3367,7 +3366,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
#endif /* FF_FS_EXFAT */
{
if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) {
EFSPRINTF("FAT - Sector size does not match physical sector size!");
EFSPRINTF("32SPS");
return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */
}
@@ -3540,7 +3539,7 @@ FRESULT f_mount (
/* Get logical drive number */
vol = get_ldnumber(&rp);
if (vol < 0) {
EFSPRINTF("Invalid drive!");
EFSPRINTF("IDRIVE!");
return FR_INVALID_DRIVE;
}
cfs = FatFs[vol]; /* Pointer to fs object */
@@ -3784,11 +3783,11 @@ FRESULT f_read (
*br = 0; /* Clear read byte counter */
res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) {
EFSPRINTF("File object Validation!");
EFSPRINTF("FOV");
LEAVE_FF(fs, res); /* Check validity */
}
if (!(fp->flag & FA_READ)) {
EFSPRINTF("Access denied!");
EFSPRINTF("NOACCESS");
LEAVE_FF(fs, FR_DENIED); /* Check access mode */
}
remain = fp->obj.objsize - fp->fptr;
@@ -3812,18 +3811,17 @@ FRESULT f_read (
}
}
if (clst < 2) {
EFSPRINTF("Cluster status check or Internal error!");
EFSPRINTF("CCHK");
ABORT(fs, FR_INT_ERR);
}
if (clst == 0xFFFFFFFF) {
EFSPRINTF("Disk error (cluster hard error)!");
EFSPRINTF("DSKC");
ABORT(fs, FR_DISK_ERR);
}
fp->clust = clst; /* Update current cluster */
}
sect = clst2sect(fs, fp->clust); /* Get current sector */
if (sect == 0) {
EFSPRINTF("Get current sector error!");
ABORT(fs, FR_INT_ERR);
}
sect += csect;
@@ -3833,7 +3831,7 @@ FRESULT f_read (
cc = fs->csize - csect;
}
if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) {
EFSPRINTF("Read - Low level disk I/O!");
EFSPRINTF("RLIO");
ABORT(fs, FR_DISK_ERR);
}
#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
@@ -3855,14 +3853,14 @@ FRESULT f_read (
#if !FF_FS_READONLY
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
EFSPRINTF("Write-back dirty sector cache!");
EFSPRINTF("RDC");
ABORT(fs, FR_DISK_ERR);
}
fp->flag &= (BYTE)~FA_DIRTY;
}
#endif
if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
EFSPRINTF("Read - Fill sector cache");
EFSPRINTF("RSC");
ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
}
}
@@ -3907,11 +3905,11 @@ FRESULT f_write (
*bw = 0; /* Clear write byte counter */
res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) {
EFSPRINTF("File object Validation!");
EFSPRINTF("FOV");
LEAVE_FF(fs, res); /* Check validity */
}
if (!(fp->flag & FA_WRITE)) {
EFSPRINTF("Access denied!");
EFSPRINTF("NOACCESS");
LEAVE_FF(fs, FR_DENIED); /* Check access mode */
}
@@ -3941,15 +3939,15 @@ FRESULT f_write (
}
}
if (clst == 0) {
EFSPRINTF("Could not allocate a new cluster\n(disk full or low level disk I/O error)!");
EFSPRINTF("DSKFULL");
break; /* Could not allocate a new cluster (disk full) */
}
if (clst == 1) {
EFSPRINTF("Cluster status check or Internal error!");
EFSPRINTF("CCHK");
ABORT(fs, FR_INT_ERR);
}
if (clst == 0xFFFFFFFF) {
EFSPRINTF("Disk error (cluster hard error)!");
EFSPRINTF("DERR");
ABORT(fs, FR_DISK_ERR);
}
fp->clust = clst; /* Update current cluster */
@@ -3966,7 +3964,6 @@ FRESULT f_write (
#endif
sect = clst2sect(fs, fp->clust); /* Get current sector */
if (sect == 0) {
EFSPRINTF("Get current sector error!");
ABORT(fs, FR_INT_ERR);
}
sect += csect;
@@ -3976,7 +3973,7 @@ FRESULT f_write (
cc = fs->csize - csect;
}
if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) {
EFSPRINTF("Write - Low level disk I/O!");
EFSPRINTF("WLIO");
ABORT(fs, FR_DISK_ERR);
}
#if FF_FS_MINIMIZE <= 2
@@ -4946,6 +4943,7 @@ FRESULT f_mkdir (
{
FRESULT res;
DIR dj;
FFOBJID sobj;
FATFS *fs;
BYTE *dir;
DWORD dcl, pcl, tm;
@@ -4963,8 +4961,8 @@ FRESULT f_mkdir (
res = FR_INVALID_NAME;
}
if (res == FR_NO_FILE) { /* Can create a new directory */
dcl = create_chain(&dj.obj, 0); /* Allocate a cluster for the new directory table */
dj.obj.objsize = (DWORD)fs->csize * SS(fs);
sobj.fs = fs; /* New object id to create a new chain */
dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */
res = FR_OK;
if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */
if (dcl == 1) res = FR_INT_ERR;
@@ -4994,8 +4992,8 @@ FRESULT f_mkdir (
if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */
st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */
st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */
st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)dj.obj.objsize); /* File size needs to be valid */
st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)dj.obj.objsize);
st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs)); /* File size needs to be valid */
st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs));
fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */
fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */
res = store_xdir(&dj);

2
ipl/ff.h → bootloader/libs/fatfs/ff.h Executable file → Normal file
View File

@@ -26,7 +26,7 @@
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "../../utils/types.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if FF_DEFINED != FFCONF_DEF

2
ipl/ffconf.h → bootloader/libs/fatfs/ffconf.h Executable file → Normal file
View File

@@ -33,7 +33,7 @@
/ 2: Enable with LF-CRLF conversion. */
#define FF_USE_FIND 0
#define FF_USE_FIND 1
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */

View File

@@ -6,7 +6,7 @@
#include "ff.h"
#include "heap.h"
#include "../../mem/heap.h"

0
ipl/ffunicode.c → bootloader/libs/fatfs/ffunicode.c Executable file → Normal file
View File

0
ipl/link.ld → bootloader/link.ld Executable file → Normal file
View File

1585
ipl/main.c → bootloader/main.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

38
ipl/emc.h → bootloader/mem/emc.h Executable file → Normal file
View File

@@ -1,23 +1,23 @@
/*
* arch/arm/mach-tegra/tegra21_emc.h
*
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
* arch/arm/mach-tegra/tegra21_emc.h
*
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef _EMC_H_
#define _EMC_H_

61
ipl/heap.c → bootloader/mem/heap.c Executable file → Normal file
View File

@@ -1,35 +1,23 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 M4xw
*
* 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 "heap.h"
typedef struct _hnode
{
int used;
u32 size;
struct _hnode *prev;
struct _hnode *next;
} hnode_t;
typedef struct _heap
{
u32 start;
hnode_t *first;
} heap_t;
#include "../../common/common_heap.h"
static void _heap_create(heap_t *heap, u32 start)
{
@@ -37,12 +25,12 @@ static void _heap_create(heap_t *heap, u32 start)
heap->first = NULL;
}
static u32 _heap_alloc(heap_t *heap, u32 size)
static u32 _heap_alloc(heap_t *heap, u32 size, u32 alignment)
{
hnode_t *node, *new;
int search = 1;
size = ALIGN(size, 0x10);
size = ALIGN(size, alignment);
if (!heap->first)
{
@@ -110,7 +98,7 @@ static void _heap_free(heap_t *heap, u32 addr)
}
}
static heap_t _heap;
heap_t _heap;
void heap_init(u32 base)
{
@@ -119,18 +107,23 @@ void heap_init(u32 base)
void *malloc(u32 size)
{
return (void *)_heap_alloc(&_heap, size);
return (void *)_heap_alloc(&_heap, size, 0x10);
}
void *memalign(u32 align, u32 size)
{
return (void *)_heap_alloc(&_heap, size, align);
}
void *calloc(u32 num, u32 size)
{
void *res = (void *)_heap_alloc(&_heap, num * size);
void *res = (void *)_heap_alloc(&_heap, num * size, 0x10);
memset(res, 0, num * size);
return res;
}
void free(void *buf)
{
if (buf != NULL)
if ((buf != NULL) || ((u32)buf > (_heap.start - 1)))
_heap_free(&_heap, (u32)buf);
}

28
bootloader/mem/heap.h Normal file
View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _HEAP_H_
#define _HEAP_H_
#include "../utils/types.h"
void heap_init(u32 base);
void *malloc(u32 size);
void *calloc(u32 num, u32 size);
void free(void *buf);
void *memalign(u32 align, u32 size);
#endif

57
ipl/mc.c → bootloader/mem/mc.c Executable file → Normal file
View File

@@ -1,9 +1,9 @@
#include "mc.h"
#include "t210.h"
#include "clock.h"
#include "util.h"
#include "../mem/mc.h"
#include "../soc/t210.h"
#include "../soc/clock.h"
#include "../utils/util.h"
void mc_config_tsec_carveout(u32 bom, u32 size1mb, int lock)
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock)
{
MC(MC_SEC_CARVEOUT_BOM) = bom;
MC(MC_SEC_CARVEOUT_SIZE_MB) = size1mb;
@@ -20,9 +20,9 @@ void mc_config_carveout()
MC(MC_VIDEO_PROTECT_SIZE_MB) = 0;
MC(MC_VIDEO_PROTECT_REG_CTRL) = 1;
//Configure TSEC carveout @ 0x90000000, 1MB.
//mc_config_tsec_carveout(0x90000000, 1, 0);
mc_config_tsec_carveout(0, 0, 1);
// Configure TSEC carveout @ 0x90000000, 1MB.
//mc_config_tsec_carveout(0x90000000, 1, false);
mc_config_tsec_carveout(0, 0, true);
MC(MC_MTS_CARVEOUT_BOM) = 0;
MC(MC_MTS_CARVEOUT_SIZE_MB) = 0;
@@ -42,20 +42,7 @@ void mc_config_carveout()
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT1_CFG0) = 0x4000006;
MC(MC_SECURITY_CARVEOUT2_BOM) = 0x80020000;
MC(MC_SECURITY_CARVEOUT2_BOM_HI) = 0;
MC(MC_SECURITY_CARVEOUT2_SIZE_128KB) = 2;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = 0x3000000;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = 0x300;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT2_CFG0) = 0x440167E;
MC(MC_SECURITY_CARVEOUT3_BOM) = 0;
MC(MC_SECURITY_CARVEOUT3_BOM_HI) = 0;
MC(MC_SECURITY_CARVEOUT3_SIZE_128KB) = 0;
@@ -100,6 +87,24 @@ void mc_config_carveout()
MC(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F;
}
void mc_config_carveout_finalize()
{
MC(MC_SECURITY_CARVEOUT2_BOM) = 0x80020000;
MC(MC_SECURITY_CARVEOUT2_BOM_HI) = 0;
MC(MC_SECURITY_CARVEOUT2_SIZE_128KB) = 2;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = 0x3000000;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = 0x300;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT2_CFG0) = 0x440167E;
}
void mc_enable_ahb_redirect()
{
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = (CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) & 0xFFF7FFFF) | 0x80000;
@@ -112,7 +117,7 @@ void mc_disable_ahb_redirect()
{
MC(MC_IRAM_BOM) = 0xFFFFF000;
MC(MC_IRAM_TOM) = 0;
//Disable IRAM_CFG_WRITE_ACCESS (sticky).
// Disable IRAM_CFG_WRITE_ACCESS (sticky).
//MC(MC_IRAM_REG_CTRL) = MC(MC_IRAM_REG_CTRL) & 0xFFFFFFFE | 1;
CLOCK(0x3A4) &= 0xFFF7FFFF;
}
@@ -120,11 +125,11 @@ void mc_disable_ahb_redirect()
void mc_enable()
{
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000;
//Enable MIPI CAL clock.
// Enable MIPI CAL clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF) | 0x2000000;
//Enable MC clock.
// Enable MC clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE) | 1;
//Enable EMC DLL clock.
// Enable EMC DLL clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & 0xFFFFBFFF) | 0x4000;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x2000001; //Clear EMC and MC reset.
usleep(5);

14
bootloader/mem/mc.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef _MC_H_
#define _MC_H_
#include "../utils/types.h"
#include "../mem/mc_t210.h"
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock);
void mc_config_carveout();
void mc_config_carveout_finalize();
void mc_enable_ahb_redirect();
void mc_disable_ahb_redirect();
void mc_enable();
#endif

22
ipl/mc_t210.h → bootloader/mem/mc_t210.h Executable file → Normal file
View File

@@ -1,15 +1,15 @@
/*
* Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that 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.
*/
* Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that 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.
*/
#ifndef _MC_T210_H_
#define _MC_T210_H_

54
ipl/sdram.c → bootloader/mem/sdram.c Executable file → Normal file
View File

@@ -1,37 +1,37 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 "i2c.h"
#include "t210.h"
#include "../soc/i2c.h"
#include "../soc/t210.h"
#include "mc.h"
#include "emc.h"
#include "pmc.h"
#include "util.h"
#include "fuse.h"
#include "max77620.h"
#include "sdram_param_t210.h"
#include "clock.h"
#include "../soc/pmc.h"
#include "../utils/util.h"
#include "../soc/fuse.h"
#include "../power/max77620.h"
#include "../mem/sdram_param_t210.h"
#include "../soc/clock.h"
#define CONFIG_SDRAM_COMPRESS_CFG
#ifdef CONFIG_SDRAM_COMPRESS_CFG
#include "lz.h"
#include "sdram_lz.inl"
#include "../libs/compr/lz.h"
#include "sdram_config_lz.inl"
#else
#include "sdram.inl"
#include "sdram_config.inl"
#endif
static u32 _get_sdram_id()
@@ -507,8 +507,8 @@ void sdram_init()
//TODO: sdram_id should be in [0,4].
const sdram_params_t *params = (const sdram_params_t *)sdram_get_params();
i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_SD_CFG2, 0x05);
i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_SD1, 40); //40 = (1000 * 1100 - 600000) / 12500 -> 1.1V
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 0x05);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD1, 40); //40 = (1000 * 1100 - 600000) / 12500 -> 1.1V
PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
usleep(params->pmc_vddp_sel_wait);

24
bootloader/mem/sdram.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _SDRAM_H_
#define _SDRAM_H_
void sdram_init();
const void *sdram_get_params();
void sdram_lp0_save_params(const void *params);
#endif

28
ipl/sdram.inl → bootloader/mem/sdram_config.inl Executable file → Normal file
View File

@@ -1,18 +1,18 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
static const u8 _dram_cfg_0[1896] = {
0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,

28
ipl/sdram_lz.inl → bootloader/mem/sdram_config_lz.inl Executable file → Normal file
View File

@@ -1,18 +1,18 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
static const u8 _dram_cfg_lz[1262] = {
0x17, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,

15
ipl/sdram_lp0.c → bootloader/mem/sdram_lp0.c Executable file → Normal file
View File

@@ -14,9 +14,9 @@
* more details.
*/
#include "t210.h"
#include "pmc_t210_lp0.h"
#include "sdram_param_t210_lp0.h"
#include "../soc/t210.h"
#include "../soc/pmc_lp0_t210.h"
#include "sdram_lp0_param_t210.h"
/*
* This function reads SDRAM parameters from the common BCT format and
@@ -47,7 +47,7 @@ void sdram_lp0_save_params(const void *params)
#define c32(value, pmcreg) pmc->pmcreg = value
//TODO: pkg1.1 (1.X - 3.X) reads them from MC.
//Patch carveout parameters.
// Patch carveout parameters.
/*sdram->McGeneralizedCarveout1Bom = 0;
sdram->McGeneralizedCarveout1BomHi = 0;
sdram->McGeneralizedCarveout1Size128kb = 0;
@@ -120,14 +120,14 @@ void sdram_lp0_save_params(const void *params)
sdram->McGeneralizedCarveout5Cfg0 = 0x8F;*/
//TODO: this is 4.X+ behaviour which seems to work fine for < 4.X.
//Patch carveout parameters.
// Patch carveout parameters.
sdram->McGeneralizedCarveout1Cfg0 = 0;
sdram->McGeneralizedCarveout2Cfg0 = 0;
sdram->McGeneralizedCarveout3Cfg0 = 0;
sdram->McGeneralizedCarveout4Cfg0 = 0;
sdram->McGeneralizedCarveout5Cfg0 = 0;
//Patch SDRAM parameters.
// Patch SDRAM parameters.
u32 t0 = sdram->EmcSwizzleRank0Byte0 << 5 >> 29 > sdram->EmcSwizzleRank0Byte0 << 1 >> 29;
u32 t1 = (t0 & 0xFFFFFFEF) | ((sdram->EmcSwizzleRank1Byte0 << 5 >> 29 > sdram->EmcSwizzleRank1Byte0 << 1 >> 29) << 4);
u32 t2 = (t1 & 0xFFFFFFFD) | ((sdram->EmcSwizzleRank0Byte1 << 5 >> 29 > sdram->EmcSwizzleRank0Byte1 << 1 >> 29) << 1);
@@ -837,7 +837,8 @@ void sdram_lp0_save_params(const void *params)
s(EmcAutoCalWait, 9:0, scratch101, 31:22);
s(SwizzleRankByteEncode, 15:0, scratch190, 15:0);
switch (sdram->MemoryType) {
switch (sdram->MemoryType)
{
case NvBootMemoryType_LpDdr2:
case NvBootMemoryType_LpDdr4:
s(EmcMrwLpddr2ZcalWarmBoot, 23:16, scratch5, 7:0);

View File

@@ -0,0 +1,964 @@
/*
* Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved.
* Copyright 2014 Google Inc.
* 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.
*/
/**
* Defines the SDRAM parameter structure.
*
* Note that PLLM is used by EMC. The field names are in camel case to ease
* directly converting BCT config files (*.cfg) into C structure.
*/
#ifndef __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__
#define __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__
#include "../utils/types.h"
enum
{
/* Specifies the memory type to be undefined */
NvBootMemoryType_None = 0,
/* Specifies the memory type to be DDR SDRAM */
NvBootMemoryType_Ddr = 0,
/* Specifies the memory type to be LPDDR SDRAM */
NvBootMemoryType_LpDdr = 0,
/* Specifies the memory type to be DDR2 SDRAM */
NvBootMemoryType_Ddr2 = 0,
/* Specifies the memory type to be LPDDR2 SDRAM */
NvBootMemoryType_LpDdr2,
/* Specifies the memory type to be DDR3 SDRAM */
NvBootMemoryType_Ddr3,
/* Specifies the memory type to be LPDDR4 SDRAM */
NvBootMemoryType_LpDdr4,
NvBootMemoryType_Num,
/* Specifies an entry in the ram_code table that's not in use */
NvBootMemoryType_Unused = 0X7FFFFFF,
};
/**
* Defines the SDRAM parameter structure
*/
struct sdram_params
{
/* Specifies the type of memory device */
u32 MemoryType;
/* MC/EMC clock source configuration */
/* Specifies the M value for PllM */
u32 PllMInputDivider;
/* Specifies the N value for PllM */
u32 PllMFeedbackDivider;
/* Specifies the time to wait for PLLM to lock (in microseconds) */
u32 PllMStableTime;
/* Specifies misc. control bits */
u32 PllMSetupControl;
/* Specifies the P value for PLLM */
u32 PllMPostDivider;
/* Specifies value for Charge Pump Gain Control */
u32 PllMKCP;
/* Specifies VCO gain */
u32 PllMKVCO;
/* Spare BCT param */
u32 EmcBctSpare0;
/* Spare BCT param */
u32 EmcBctSpare1;
/* Spare BCT param */
u32 EmcBctSpare2;
/* Spare BCT param */
u32 EmcBctSpare3;
/* Spare BCT param */
u32 EmcBctSpare4;
/* Spare BCT param */
u32 EmcBctSpare5;
/* Spare BCT param */
u32 EmcBctSpare6;
/* Spare BCT param */
u32 EmcBctSpare7;
/* Spare BCT param */
u32 EmcBctSpare8;
/* Spare BCT param */
u32 EmcBctSpare9;
/* Spare BCT param */
u32 EmcBctSpare10;
/* Spare BCT param */
u32 EmcBctSpare11;
/* Spare BCT param */
u32 EmcBctSpare12;
/* Spare BCT param */
u32 EmcBctSpare13;
/* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */
u32 EmcClockSource;
u32 EmcClockSourceDll;
/* Defines possible override for PLLLM_MISC2 */
u32 ClkRstControllerPllmMisc2Override;
/* enables override for PLLLM_MISC2 */
u32 ClkRstControllerPllmMisc2OverrideEnable;
/* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */
u32 ClearClk2Mc1;
/* Auto-calibration of EMC pads */
/* Specifies the value for EMC_AUTO_CAL_INTERVAL */
u32 EmcAutoCalInterval;
/*
* Specifies the value for EMC_AUTO_CAL_CONFIG
* Note: Trigger bits are set by the SDRAM code.
*/
u32 EmcAutoCalConfig;
/* Specifies the value for EMC_AUTO_CAL_CONFIG2 */
u32 EmcAutoCalConfig2;
/* Specifies the value for EMC_AUTO_CAL_CONFIG3 */
u32 EmcAutoCalConfig3;
/* Specifies the values for EMC_AUTO_CAL_CONFIG4-8 */
u32 EmcAutoCalConfig4;
u32 EmcAutoCalConfig5;
u32 EmcAutoCalConfig6;
u32 EmcAutoCalConfig7;
u32 EmcAutoCalConfig8;
/* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */
u32 EmcAutoCalVrefSel0;
u32 EmcAutoCalVrefSel1;
/* Specifies the value for EMC_AUTO_CAL_CHANNEL */
u32 EmcAutoCalChannel;
/* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */
u32 EmcPmacroAutocalCfg0;
u32 EmcPmacroAutocalCfg1;
u32 EmcPmacroAutocalCfg2;
u32 EmcPmacroRxTerm;
u32 EmcPmacroDqTxDrv;
u32 EmcPmacroCaTxDrv;
u32 EmcPmacroCmdTxDrv;
u32 EmcPmacroAutocalCfgCommon;
u32 EmcPmacroZctrl;
/*
* Specifies the time for the calibration
* to stabilize (in microseconds)
*/
u32 EmcAutoCalWait;
u32 EmcXm2CompPadCtrl;
u32 EmcXm2CompPadCtrl2;
u32 EmcXm2CompPadCtrl3;
/*
* DRAM size information
* Specifies the value for EMC_ADR_CFG
*/
u32 EmcAdrCfg;
/*
* Specifies the time to wait after asserting pin
* CKE (in microseconds)
*/
u32 EmcPinProgramWait;
/* Specifies the extra delay before/after pin RESET/CKE command */
u32 EmcPinExtraWait;
u32 EmcPinGpioEn;
u32 EmcPinGpio;
/*
* Specifies the extra delay after the first writing
* of EMC_TIMING_CONTROL
*/
u32 EmcTimingControlWait;
/* Timing parameters required for the SDRAM */
/* Specifies the value for EMC_RC */
u32 EmcRc;
/* Specifies the value for EMC_RFC */
u32 EmcRfc;
/* Specifies the value for EMC_RFC_PB */
u32 EmcRfcPb;
/* Specifies the value for EMC_RFC_CTRL2 */
u32 EmcRefctrl2;
/* Specifies the value for EMC_RFC_SLR */
u32 EmcRfcSlr;
/* Specifies the value for EMC_RAS */
u32 EmcRas;
/* Specifies the value for EMC_RP */
u32 EmcRp;
/* Specifies the value for EMC_R2R */
u32 EmcR2r;
/* Specifies the value for EMC_W2W */
u32 EmcW2w;
/* Specifies the value for EMC_R2W */
u32 EmcR2w;
/* Specifies the value for EMC_W2R */
u32 EmcW2r;
/* Specifies the value for EMC_R2P */
u32 EmcR2p;
/* Specifies the value for EMC_W2P */
u32 EmcW2p;
u32 EmcTppd;
u32 EmcCcdmw;
/* Specifies the value for EMC_RD_RCD */
u32 EmcRdRcd;
/* Specifies the value for EMC_WR_RCD */
u32 EmcWrRcd;
/* Specifies the value for EMC_RRD */
u32 EmcRrd;
/* Specifies the value for EMC_REXT */
u32 EmcRext;
/* Specifies the value for EMC_WEXT */
u32 EmcWext;
/* Specifies the value for EMC_WDV */
u32 EmcWdv;
u32 EmcWdvChk;
u32 EmcWsv;
u32 EmcWev;
/* Specifies the value for EMC_WDV_MASK */
u32 EmcWdvMask;
u32 EmcWsDuration;
u32 EmcWeDuration;
/* Specifies the value for EMC_QUSE */
u32 EmcQUse;
/* Specifies the value for EMC_QUSE_WIDTH */
u32 EmcQuseWidth;
/* Specifies the value for EMC_IBDLY */
u32 EmcIbdly;
/* Specifies the value for EMC_OBDLY */
u32 EmcObdly;
/* Specifies the value for EMC_EINPUT */
u32 EmcEInput;
/* Specifies the value for EMC_EINPUT_DURATION */
u32 EmcEInputDuration;
/* Specifies the value for EMC_PUTERM_EXTRA */
u32 EmcPutermExtra;
/* Specifies the value for EMC_PUTERM_WIDTH */
u32 EmcPutermWidth;
/* Specifies the value for EMC_PUTERM_ADJ */
////u32 EmcPutermAdj;
/* Specifies the value for EMC_QRST */
u32 EmcQRst;
/* Specifies the value for EMC_QSAFE */
u32 EmcQSafe;
/* Specifies the value for EMC_RDV */
u32 EmcRdv;
/* Specifies the value for EMC_RDV_MASK */
u32 EmcRdvMask;
/* Specifies the value for EMC_RDV_EARLY */
u32 EmcRdvEarly;
/* Specifies the value for EMC_RDV_EARLY_MASK */
u32 EmcRdvEarlyMask;
/* Specifies the value for EMC_QPOP */
u32 EmcQpop;
/* Specifies the value for EMC_REFRESH */
u32 EmcRefresh;
/* Specifies the value for EMC_BURST_REFRESH_NUM */
u32 EmcBurstRefreshNum;
/* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */
u32 EmcPreRefreshReqCnt;
/* Specifies the value for EMC_PDEX2WR */
u32 EmcPdEx2Wr;
/* Specifies the value for EMC_PDEX2RD */
u32 EmcPdEx2Rd;
/* Specifies the value for EMC_PCHG2PDEN */
u32 EmcPChg2Pden;
/* Specifies the value for EMC_ACT2PDEN */
u32 EmcAct2Pden;
/* Specifies the value for EMC_AR2PDEN */
u32 EmcAr2Pden;
/* Specifies the value for EMC_RW2PDEN */
u32 EmcRw2Pden;
/* Specifies the value for EMC_CKE2PDEN */
u32 EmcCke2Pden;
/* Specifies the value for EMC_PDEX2CKE */
u32 EmcPdex2Cke;
/* Specifies the value for EMC_PDEX2MRR */
u32 EmcPdex2Mrr;
/* Specifies the value for EMC_TXSR */
u32 EmcTxsr;
/* Specifies the value for EMC_TXSRDLL */
u32 EmcTxsrDll;
/* Specifies the value for EMC_TCKE */
u32 EmcTcke;
/* Specifies the value for EMC_TCKESR */
u32 EmcTckesr;
/* Specifies the value for EMC_TPD */
u32 EmcTpd;
/* Specifies the value for EMC_TFAW */
u32 EmcTfaw;
/* Specifies the value for EMC_TRPAB */
u32 EmcTrpab;
/* Specifies the value for EMC_TCLKSTABLE */
u32 EmcTClkStable;
/* Specifies the value for EMC_TCLKSTOP */
u32 EmcTClkStop;
/* Specifies the value for EMC_TREFBW */
u32 EmcTRefBw;
/* FBIO configuration values */
/* Specifies the value for EMC_FBIO_CFG5 */
u32 EmcFbioCfg5;
/* Specifies the value for EMC_FBIO_CFG7 */
u32 EmcFbioCfg7;
/* Specifies the value for EMC_FBIO_CFG8 */
u32 EmcFbioCfg8;
/* Command mapping for CMD brick 0 */
u32 EmcCmdMappingCmd0_0;
u32 EmcCmdMappingCmd0_1;
u32 EmcCmdMappingCmd0_2;
u32 EmcCmdMappingCmd1_0;
u32 EmcCmdMappingCmd1_1;
u32 EmcCmdMappingCmd1_2;
u32 EmcCmdMappingCmd2_0;
u32 EmcCmdMappingCmd2_1;
u32 EmcCmdMappingCmd2_2;
u32 EmcCmdMappingCmd3_0;
u32 EmcCmdMappingCmd3_1;
u32 EmcCmdMappingCmd3_2;
u32 EmcCmdMappingByte;
/* Specifies the value for EMC_FBIO_SPARE */
u32 EmcFbioSpare;
/* Specifies the value for EMC_CFG_RSV */
u32 EmcCfgRsv;
/* MRS command values */
/* Specifies the value for EMC_MRS */
u32 EmcMrs;
/* Specifies the MP0 command to initialize mode registers */
u32 EmcEmrs;
/* Specifies the MP2 command to initialize mode registers */
u32 EmcEmrs2;
/* Specifies the MP3 command to initialize mode registers */
u32 EmcEmrs3;
/* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */
u32 EmcMrw1;
/* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */
u32 EmcMrw2;
/* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */
u32 EmcMrw3;
/* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */
u32 EmcMrw4;
/* Specifies the programming to LPDDR2 Mode Register 3? at cold boot */
u32 EmcMrw6;
/* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */
u32 EmcMrw8;
/* Specifies the programming to LPDDR2 Mode Register 11? at cold boot */
u32 EmcMrw9;
/* Specifies the programming to LPDDR2 Mode Register 12 at cold boot */
u32 EmcMrw10;
/* Specifies the programming to LPDDR2 Mode Register 14 at cold boot */
u32 EmcMrw12;
/* Specifies the programming to LPDDR2 Mode Register 14? at cold boot */
u32 EmcMrw13;
/* Specifies the programming to LPDDR2 Mode Register 22 at cold boot */
u32 EmcMrw14;
/*
* Specifies the programming to extra LPDDR2 Mode Register
* at cold boot
*/
u32 EmcMrwExtra;
/*
* Specifies the programming to extra LPDDR2 Mode Register
* at warm boot
*/
u32 EmcWarmBootMrwExtra;
/*
* Specify the enable of extra Mode Register programming at
* warm boot
*/
u32 EmcWarmBootExtraModeRegWriteEnable;
/*
* Specify the enable of extra Mode Register programming at
* cold boot
*/
u32 EmcExtraModeRegWriteEnable;
/* Specifies the EMC_MRW reset command value */
u32 EmcMrwResetCommand;
/* Specifies the EMC Reset wait time (in microseconds) */
u32 EmcMrwResetNInitWait;
/* Specifies the value for EMC_MRS_WAIT_CNT */
u32 EmcMrsWaitCnt;
/* Specifies the value for EMC_MRS_WAIT_CNT2 */
u32 EmcMrsWaitCnt2;
/* EMC miscellaneous configurations */
/* Specifies the value for EMC_CFG */
u32 EmcCfg;
/* Specifies the value for EMC_CFG_2 */
u32 EmcCfg2;
/* Specifies the pipe bypass controls */
u32 EmcCfgPipe;
u32 EmcCfgPipeClk;
u32 EmcFdpdCtrlCmdNoRamp;
u32 EmcCfgUpdate;
/* Specifies the value for EMC_DBG */
u32 EmcDbg;
u32 EmcDbgWriteMux;
/* Specifies the value for EMC_CMDQ */
u32 EmcCmdQ;
/* Specifies the value for EMC_MC2EMCQ */
u32 EmcMc2EmcQ;
/* Specifies the value for EMC_DYN_SELF_REF_CONTROL */
u32 EmcDynSelfRefControl;
/* Specifies the value for MEM_INIT_DONE */
u32 AhbArbitrationXbarCtrlMemInitDone;
/* Specifies the value for EMC_CFG_DIG_DLL */
u32 EmcCfgDigDll;
u32 EmcCfgDigDll_1;
/* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */
u32 EmcCfgDigDllPeriod;
/* Specifies the value of *DEV_SELECTN of various EMC registers */
u32 EmcDevSelect;
/* Specifies the value for EMC_SEL_DPD_CTRL */
u32 EmcSelDpdCtrl;
/* Pads trimmer delays */
u32 EmcFdpdCtrlDq;
u32 EmcFdpdCtrlCmd;
u32 EmcPmacroIbVrefDq_0;
u32 EmcPmacroIbVrefDq_1;
u32 EmcPmacroIbVrefDqs_0;
u32 EmcPmacroIbVrefDqs_1;
u32 EmcPmacroIbRxrt;
u32 EmcCfgPipe1;
u32 EmcCfgPipe2;
/* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */
u32 EmcPmacroQuseDdllRank0_0;
u32 EmcPmacroQuseDdllRank0_1;
u32 EmcPmacroQuseDdllRank0_2;
u32 EmcPmacroQuseDdllRank0_3;
u32 EmcPmacroQuseDdllRank0_4;
u32 EmcPmacroQuseDdllRank0_5;
u32 EmcPmacroQuseDdllRank1_0;
u32 EmcPmacroQuseDdllRank1_1;
u32 EmcPmacroQuseDdllRank1_2;
u32 EmcPmacroQuseDdllRank1_3;
u32 EmcPmacroQuseDdllRank1_4;
u32 EmcPmacroQuseDdllRank1_5;
u32 EmcPmacroObDdllLongDqRank0_0;
u32 EmcPmacroObDdllLongDqRank0_1;
u32 EmcPmacroObDdllLongDqRank0_2;
u32 EmcPmacroObDdllLongDqRank0_3;
u32 EmcPmacroObDdllLongDqRank0_4;
u32 EmcPmacroObDdllLongDqRank0_5;
u32 EmcPmacroObDdllLongDqRank1_0;
u32 EmcPmacroObDdllLongDqRank1_1;
u32 EmcPmacroObDdllLongDqRank1_2;
u32 EmcPmacroObDdllLongDqRank1_3;
u32 EmcPmacroObDdllLongDqRank1_4;
u32 EmcPmacroObDdllLongDqRank1_5;
u32 EmcPmacroObDdllLongDqsRank0_0;
u32 EmcPmacroObDdllLongDqsRank0_1;
u32 EmcPmacroObDdllLongDqsRank0_2;
u32 EmcPmacroObDdllLongDqsRank0_3;
u32 EmcPmacroObDdllLongDqsRank0_4;
u32 EmcPmacroObDdllLongDqsRank0_5;
u32 EmcPmacroObDdllLongDqsRank1_0;
u32 EmcPmacroObDdllLongDqsRank1_1;
u32 EmcPmacroObDdllLongDqsRank1_2;
u32 EmcPmacroObDdllLongDqsRank1_3;
u32 EmcPmacroObDdllLongDqsRank1_4;
u32 EmcPmacroObDdllLongDqsRank1_5;
u32 EmcPmacroIbDdllLongDqsRank0_0;
u32 EmcPmacroIbDdllLongDqsRank0_1;
u32 EmcPmacroIbDdllLongDqsRank0_2;
u32 EmcPmacroIbDdllLongDqsRank0_3;
u32 EmcPmacroIbDdllLongDqsRank1_0;
u32 EmcPmacroIbDdllLongDqsRank1_1;
u32 EmcPmacroIbDdllLongDqsRank1_2;
u32 EmcPmacroIbDdllLongDqsRank1_3;
u32 EmcPmacroDdllLongCmd_0;
u32 EmcPmacroDdllLongCmd_1;
u32 EmcPmacroDdllLongCmd_2;
u32 EmcPmacroDdllLongCmd_3;
u32 EmcPmacroDdllLongCmd_4;
u32 EmcPmacroDdllShortCmd_0;
u32 EmcPmacroDdllShortCmd_1;
u32 EmcPmacroDdllShortCmd_2;
/*
* Specifies the delay after asserting CKE pin during a WarmBoot0
* sequence (in microseconds)
*/
u32 WarmBootWait;
/* Specifies the value for EMC_ODT_WRITE */
u32 EmcOdtWrite;
/* Periodic ZQ calibration */
/*
* Specifies the value for EMC_ZCAL_INTERVAL
* Value 0 disables ZQ calibration
*/
u32 EmcZcalInterval;
/* Specifies the value for EMC_ZCAL_WAIT_CNT */
u32 EmcZcalWaitCnt;
/* Specifies the value for EMC_ZCAL_MRW_CMD */
u32 EmcZcalMrwCmd;
/* DRAM initialization sequence flow control */
/* Specifies the MRS command value for resetting DLL */
u32 EmcMrsResetDll;
/* Specifies the command for ZQ initialization of device 0 */
u32 EmcZcalInitDev0;
/* Specifies the command for ZQ initialization of device 1 */
u32 EmcZcalInitDev1;
/*
* Specifies the wait time after programming a ZQ initialization
* command (in microseconds)
*/
u32 EmcZcalInitWait;
/*
* Specifies the enable for ZQ calibration at cold boot [bit 0]
* and warm boot [bit 1]
*/
u32 EmcZcalWarmColdBootEnables;
/*
* Specifies the MRW command to LPDDR2 for ZQ calibration
* on warmboot
*/
/* Is issued to both devices separately */
u32 EmcMrwLpddr2ZcalWarmBoot;
/*
* Specifies the ZQ command to DDR3 for ZQ calibration on warmboot
* Is issued to both devices separately
*/
u32 EmcZqCalDdr3WarmBoot;
u32 EmcZqCalLpDdr4WarmBoot;
/*
* Specifies the wait time for ZQ calibration on warmboot
* (in microseconds)
*/
u32 EmcZcalWarmBootWait;
/*
* Specifies the enable for DRAM Mode Register programming
* at warm boot
*/
u32 EmcMrsWarmBootEnable;
/*
* Specifies the wait time after sending an MRS DLL reset command
* in microseconds)
*/
u32 EmcMrsResetDllWait;
/* Specifies the extra MRS command to initialize mode registers */
u32 EmcMrsExtra;
/* Specifies the extra MRS command at warm boot */
u32 EmcWarmBootMrsExtra;
/* Specifies the EMRS command to enable the DDR2 DLL */
u32 EmcEmrsDdr2DllEnable;
/* Specifies the MRS command to reset the DDR2 DLL */
u32 EmcMrsDdr2DllReset;
/* Specifies the EMRS command to set OCD calibration */
u32 EmcEmrsDdr2OcdCalib;
/*
* Specifies the wait between initializing DDR and setting OCD
* calibration (in microseconds)
*/
u32 EmcDdr2Wait;
/* Specifies the value for EMC_CLKEN_OVERRIDE */
u32 EmcClkenOverride;
/*
* Specifies LOG2 of the extra refresh numbers after booting
* Program 0 to disable
*/
u32 EmcExtraRefreshNum;
/* Specifies the master override for all EMC clocks */
u32 EmcClkenOverrideAllWarmBoot;
/* Specifies the master override for all MC clocks */
u32 McClkenOverrideAllWarmBoot;
/* Specifies digital dll period, choosing between 4 to 64 ms */
u32 EmcCfgDigDllPeriodWarmBoot;
/* Pad controls */
/* Specifies the value for PMC_VDDP_SEL */
u32 PmcVddpSel;
/* Specifies the wait time after programming PMC_VDDP_SEL */
u32 PmcVddpSelWait;
/* Specifies the value for PMC_DDR_PWR */
u32 PmcDdrPwr;
/* Specifies the value for PMC_DDR_CFG */
u32 PmcDdrCfg;
/* Specifies the value for PMC_IO_DPD3_REQ */
u32 PmcIoDpd3Req;
/* Specifies the wait time after programming PMC_IO_DPD3_REQ */
u32 PmcIoDpd3ReqWait;
u32 PmcIoDpd4ReqWait;
/* Specifies the value for PMC_REG_SHORT */
u32 PmcRegShort;
/* Specifies the value for PMC_NO_IOPOWER */
u32 PmcNoIoPower;
u32 PmcDdrCntrlWait;
u32 PmcDdrCntrl;
/* Specifies the value for EMC_ACPD_CONTROL */
u32 EmcAcpdControl;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE_CFG */
////u32 EmcSwizzleRank0ByteCfg;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */
u32 EmcSwizzleRank0Byte0;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */
u32 EmcSwizzleRank0Byte1;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */
u32 EmcSwizzleRank0Byte2;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */
u32 EmcSwizzleRank0Byte3;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE_CFG */
////u32 EmcSwizzleRank1ByteCfg;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */
u32 EmcSwizzleRank1Byte0;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */
u32 EmcSwizzleRank1Byte1;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */
u32 EmcSwizzleRank1Byte2;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */
u32 EmcSwizzleRank1Byte3;
/* Specifies the value for EMC_TXDSRVTTGEN */
u32 EmcTxdsrvttgen;
/* Specifies the value for EMC_DATA_BRLSHFT_0 */
u32 EmcDataBrlshft0;
u32 EmcDataBrlshft1;
u32 EmcDqsBrlshft0;
u32 EmcDqsBrlshft1;
u32 EmcCmdBrlshft0;
u32 EmcCmdBrlshft1;
u32 EmcCmdBrlshft2;
u32 EmcCmdBrlshft3;
u32 EmcQuseBrlshft0;
u32 EmcQuseBrlshft1;
u32 EmcQuseBrlshft2;
u32 EmcQuseBrlshft3;
u32 EmcDllCfg0;
u32 EmcDllCfg1;
u32 EmcPmcScratch1;
u32 EmcPmcScratch2;
u32 EmcPmcScratch3;
u32 EmcPmacroPadCfgCtrl;
u32 EmcPmacroVttgenCtrl0;
u32 EmcPmacroVttgenCtrl1;
u32 EmcPmacroVttgenCtrl2;
u32 EmcPmacroBrickCtrlRfu1;
u32 EmcPmacroCmdBrickCtrlFdpd;
u32 EmcPmacroBrickCtrlRfu2;
u32 EmcPmacroDataBrickCtrlFdpd;
u32 EmcPmacroBgBiasCtrl0;
u32 EmcPmacroDataPadRxCtrl;
u32 EmcPmacroCmdPadRxCtrl;
u32 EmcPmacroDataRxTermMode;
u32 EmcPmacroCmdRxTermMode;
u32 EmcPmacroDataPadTxCtrl;
u32 EmcPmacroCommonPadTxCtrl;
u32 EmcPmacroCmdPadTxCtrl;
u32 EmcCfg3;
u32 EmcPmacroTxPwrd0;
u32 EmcPmacroTxPwrd1;
u32 EmcPmacroTxPwrd2;
u32 EmcPmacroTxPwrd3;
u32 EmcPmacroTxPwrd4;
u32 EmcPmacroTxPwrd5;
u32 EmcConfigSampleDelay;
u32 EmcPmacroBrickMapping0;
u32 EmcPmacroBrickMapping1;
u32 EmcPmacroBrickMapping2;
u32 EmcPmacroTxSelClkSrc0;
u32 EmcPmacroTxSelClkSrc1;
u32 EmcPmacroTxSelClkSrc2;
u32 EmcPmacroTxSelClkSrc3;
u32 EmcPmacroTxSelClkSrc4;
u32 EmcPmacroTxSelClkSrc5;
u32 EmcPmacroDdllBypass;
u32 EmcPmacroDdllPwrd0;
u32 EmcPmacroDdllPwrd1;
u32 EmcPmacroDdllPwrd2;
u32 EmcPmacroCmdCtrl0;
u32 EmcPmacroCmdCtrl1;
u32 EmcPmacroCmdCtrl2;
/* DRAM size information */
/* Specifies the value for MC_EMEM_ADR_CFG */
u32 McEmemAdrCfg;
/* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */
u32 McEmemAdrCfgDev0;
/* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */
u32 McEmemAdrCfgDev1;
u32 McEmemAdrCfgChannelMask;
/* Specifies the value for MC_EMEM_BANK_SWIZZLECfg0 */
u32 McEmemAdrCfgBankMask0;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */
u32 McEmemAdrCfgBankMask1;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */
u32 McEmemAdrCfgBankMask2;
/*
* Specifies the value for MC_EMEM_CFG which holds the external memory
* size (in KBytes)
*/
u32 McEmemCfg;
/* MC arbitration configuration */
/* Specifies the value for MC_EMEM_ARB_CFG */
u32 McEmemArbCfg;
/* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */
u32 McEmemArbOutstandingReq;
u32 McEmemArbRefpbHpCtrl;
u32 McEmemArbRefpbBankCtrl;
/* Specifies the value for MC_EMEM_ARB_TIMING_RCD */
u32 McEmemArbTimingRcd;
/* Specifies the value for MC_EMEM_ARB_TIMING_RP */
u32 McEmemArbTimingRp;
/* Specifies the value for MC_EMEM_ARB_TIMING_RC */
u32 McEmemArbTimingRc;
/* Specifies the value for MC_EMEM_ARB_TIMING_RAS */
u32 McEmemArbTimingRas;
/* Specifies the value for MC_EMEM_ARB_TIMING_FAW */
u32 McEmemArbTimingFaw;
/* Specifies the value for MC_EMEM_ARB_TIMING_RRD */
u32 McEmemArbTimingRrd;
/* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */
u32 McEmemArbTimingRap2Pre;
/* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */
u32 McEmemArbTimingWap2Pre;
/* Specifies the value for MC_EMEM_ARB_TIMING_R2R */
u32 McEmemArbTimingR2R;
/* Specifies the value for MC_EMEM_ARB_TIMING_W2W */
u32 McEmemArbTimingW2W;
/* Specifies the value for MC_EMEM_ARB_TIMING_R2W */
u32 McEmemArbTimingR2W;
/* Specifies the value for MC_EMEM_ARB_TIMING_W2R */
u32 McEmemArbTimingW2R;
u32 McEmemArbTimingRFCPB;
/* Specifies the value for MC_EMEM_ARB_DA_TURNS */
u32 McEmemArbDaTurns;
/* Specifies the value for MC_EMEM_ARB_DA_COVERS */
u32 McEmemArbDaCovers;
/* Specifies the value for MC_EMEM_ARB_MISC0 */
u32 McEmemArbMisc0;
/* Specifies the value for MC_EMEM_ARB_MISC1 */
u32 McEmemArbMisc1;
u32 McEmemArbMisc2;
/* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */
u32 McEmemArbRing1Throttle;
/* Specifies the value for MC_EMEM_ARB_OVERRIDE */
u32 McEmemArbOverride;
/* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */
u32 McEmemArbOverride1;
/* Specifies the value for MC_EMEM_ARB_RSV */
u32 McEmemArbRsv;
u32 McDaCfg0;
u32 McEmemArbTimingCcdmw;
/* Specifies the value for MC_CLKEN_OVERRIDE */
u32 McClkenOverride;
/* Specifies the value for MC_STAT_CONTROL */
u32 McStatControl;
/* Specifies the value for MC_VIDEO_PROTECT_BOM */
u32 McVideoProtectBom;
/* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */
u32 McVideoProtectBomAdrHi;
/* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */
u32 McVideoProtectSizeMb;
/* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */
u32 McVideoProtectVprOverride;
/* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */
u32 McVideoProtectVprOverride1;
/* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */
u32 McVideoProtectGpuOverride0;
/* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */
u32 McVideoProtectGpuOverride1;
/* Specifies the value for MC_SEC_CARVEOUT_BOM */
u32 McSecCarveoutBom;
/* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */
u32 McSecCarveoutAdrHi;
/* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */
u32 McSecCarveoutSizeMb;
/* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.
VIDEO_PROTECT_WRITEAccess */
u32 McVideoProtectWriteAccess;
/* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.
SEC_CARVEOUT_WRITEAccess */
u32 McSecCarveoutProtectWriteAccess;
/* Write-Protect Regions (WPR) */
u32 McGeneralizedCarveout1Bom;
u32 McGeneralizedCarveout1BomHi;
u32 McGeneralizedCarveout1Size128kb;
u32 McGeneralizedCarveout1Access0;
u32 McGeneralizedCarveout1Access1;
u32 McGeneralizedCarveout1Access2;
u32 McGeneralizedCarveout1Access3;
u32 McGeneralizedCarveout1Access4;
u32 McGeneralizedCarveout1ForceInternalAccess0;
u32 McGeneralizedCarveout1ForceInternalAccess1;
u32 McGeneralizedCarveout1ForceInternalAccess2;
u32 McGeneralizedCarveout1ForceInternalAccess3;
u32 McGeneralizedCarveout1ForceInternalAccess4;
u32 McGeneralizedCarveout1Cfg0;
u32 McGeneralizedCarveout2Bom;
u32 McGeneralizedCarveout2BomHi;
u32 McGeneralizedCarveout2Size128kb;
u32 McGeneralizedCarveout2Access0;
u32 McGeneralizedCarveout2Access1;
u32 McGeneralizedCarveout2Access2;
u32 McGeneralizedCarveout2Access3;
u32 McGeneralizedCarveout2Access4;
u32 McGeneralizedCarveout2ForceInternalAccess0;
u32 McGeneralizedCarveout2ForceInternalAccess1;
u32 McGeneralizedCarveout2ForceInternalAccess2;
u32 McGeneralizedCarveout2ForceInternalAccess3;
u32 McGeneralizedCarveout2ForceInternalAccess4;
u32 McGeneralizedCarveout2Cfg0;
u32 McGeneralizedCarveout3Bom;
u32 McGeneralizedCarveout3BomHi;
u32 McGeneralizedCarveout3Size128kb;
u32 McGeneralizedCarveout3Access0;
u32 McGeneralizedCarveout3Access1;
u32 McGeneralizedCarveout3Access2;
u32 McGeneralizedCarveout3Access3;
u32 McGeneralizedCarveout3Access4;
u32 McGeneralizedCarveout3ForceInternalAccess0;
u32 McGeneralizedCarveout3ForceInternalAccess1;
u32 McGeneralizedCarveout3ForceInternalAccess2;
u32 McGeneralizedCarveout3ForceInternalAccess3;
u32 McGeneralizedCarveout3ForceInternalAccess4;
u32 McGeneralizedCarveout3Cfg0;
u32 McGeneralizedCarveout4Bom;
u32 McGeneralizedCarveout4BomHi;
u32 McGeneralizedCarveout4Size128kb;
u32 McGeneralizedCarveout4Access0;
u32 McGeneralizedCarveout4Access1;
u32 McGeneralizedCarveout4Access2;
u32 McGeneralizedCarveout4Access3;
u32 McGeneralizedCarveout4Access4;
u32 McGeneralizedCarveout4ForceInternalAccess0;
u32 McGeneralizedCarveout4ForceInternalAccess1;
u32 McGeneralizedCarveout4ForceInternalAccess2;
u32 McGeneralizedCarveout4ForceInternalAccess3;
u32 McGeneralizedCarveout4ForceInternalAccess4;
u32 McGeneralizedCarveout4Cfg0;
u32 McGeneralizedCarveout5Bom;
u32 McGeneralizedCarveout5BomHi;
u32 McGeneralizedCarveout5Size128kb;
u32 McGeneralizedCarveout5Access0;
u32 McGeneralizedCarveout5Access1;
u32 McGeneralizedCarveout5Access2;
u32 McGeneralizedCarveout5Access3;
u32 McGeneralizedCarveout5Access4;
u32 McGeneralizedCarveout5ForceInternalAccess0;
u32 McGeneralizedCarveout5ForceInternalAccess1;
u32 McGeneralizedCarveout5ForceInternalAccess2;
u32 McGeneralizedCarveout5ForceInternalAccess3;
u32 McGeneralizedCarveout5ForceInternalAccess4;
u32 McGeneralizedCarveout5Cfg0;
/* Specifies enable for CA training */
u32 EmcCaTrainingEnable;
/* Set if bit 6 select is greater than bit 7 select; uses aremc.
spec packet SWIZZLE_BIT6_GT_BIT7 */
u32 SwizzleRankByteEncode;
/* Specifies enable and offset for patched boot ROM write */
u32 BootRomPatchControl;
/* Specifies data for patched boot ROM write */
u32 BootRomPatchData;
/* Specifies the value for MC_MTS_CARVEOUT_BOM */
u32 McMtsCarveoutBom;
/* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */
u32 McMtsCarveoutAdrHi;
/* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */
u32 McMtsCarveoutSizeMb;
/* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */
u32 McMtsCarveoutRegCtrl;
/* End */
};
#endif /* __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__ */

View File

@@ -37,7 +37,8 @@
/**
* Defines the SDRAM parameter structure
*/
typedef struct _sdram_params {
typedef struct _sdram_params
{
/* Specifies the type of memory device */
u32 memory_type;

View File

@@ -1,24 +1,24 @@
/*
* Battery charger driver for Nintendo Switch's TI BQ24193
*
* 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/>.
*/
* Battery charger driver for Nintendo Switch's TI BQ24193
*
* 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 "bq24193.h"
#include "i2c.h"
#include "util.h"
#include "../soc/i2c.h"
#include "../utils/util.h"
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
{

View File

@@ -1,20 +1,20 @@
/*
* Battery charger driver for Nintendo Switch's TI BQ24193
*
* 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/>.
*/
* Battery charger driver for Nintendo Switch's TI BQ24193
*
* 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 __BQ24193_H_
#define __BQ24193_H_
@@ -100,17 +100,17 @@ enum BQ24193_reg {
};
enum BQ24193_reg_prop {
BQ24193_InputVoltageLimit, // REG 0.
BQ24193_InputCurrentLimit, // REG 0.
BQ24193_SystemMinimumVoltage, // REG 1.
BQ24193_InputVoltageLimit, // REG 0.
BQ24193_InputCurrentLimit, // REG 0.
BQ24193_SystemMinimumVoltage, // REG 1.
BQ24193_FastChargeCurrentLimit, // REG 2.
BQ24193_ChargeVoltageLimit, // REG 4.
BQ24193_RechargeThreshold, // REG 4.
BQ24193_ThermalRegulation, // REG 6.
BQ24193_ChargeStatus, // REG 8.
BQ24193_TempStatus, // REG 9.
BQ24193_DevID, // REG A.
BQ24193_ProductNumber, // REG A.
BQ24193_ChargeVoltageLimit, // REG 4.
BQ24193_RechargeThreshold, // REG 4.
BQ24193_ThermalRegulation, // REG 6.
BQ24193_ChargeStatus, // REG 8.
BQ24193_TempStatus, // REG 9.
BQ24193_DevID, // REG A.
BQ24193_ProductNumber, // REG A.
};
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value);

View File

@@ -23,8 +23,8 @@
*/
#include "max17050.h"
#include "i2c.h"
#include "util.h"
#include "../soc/i2c.h"
#include "../utils/util.h"
/* Status register bits */
#define STATUS_POR_BIT (1 << 1)
@@ -49,66 +49,66 @@ int max17050_get_property(enum MAX17050_reg reg, int *value)
switch (reg)
{
case MAX17050_Age: //Age (percent). Based on 100% x (FullCAP Register/DesignCap).
case MAX17050_Age: // Age (percent). Based on 100% x (FullCAP Register/DesignCap).
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_Age);
*value = data >> 8; /* Show MSB. 1% increments */
break;
case MAX17050_Cycles: //Cycle count.
case MAX17050_Cycles: // Cycle count.
i2c_recv_buf_small((u8 *)value, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_Cycles);
break;
case MAX17050_MinVolt: //Voltage max/min
case MAX17050_MinVolt: // Voltage max/min
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MinMaxVolt);
*value = (data & 0xff) * 20; /* Voltage MIN. Units of 20mV */
break;
case MAX17050_MaxVolt: //Voltage max/min
case MAX17050_MaxVolt: // Voltage max/min
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MinMaxVolt);
*value = (data >> 8) * 20; /* Voltage MAX. Units of LSB = 20mV */
break;
case MAX17050_V_empty: //Voltage min design.
case MAX17050_V_empty: // Voltage min design.
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_V_empty);
*value = (data >> 7) * 10; /* Units of LSB = 10mV */
break;
case MAX17050_VCELL: //Voltage now.
case MAX17050_VCELL: // Voltage now.
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_VCELL);
*value = data * 625 / 8 / 1000;
break;
case MAX17050_AvgVCELL: //Voltage avg.
case MAX17050_AvgVCELL: // Voltage avg.
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_AvgVCELL);
*value = data * 625 / 8 / 1000;
break;
case MAX17050_OCVInternal: //Voltage ocv.
case MAX17050_OCVInternal: // Voltage ocv.
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_OCVInternal);
*value = data * 625 / 8 / 1000;
break;
case MAX17050_RepSOC: //Capacity %.
case MAX17050_RepSOC: // Capacity %.
i2c_recv_buf_small((u8 *)value, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RepSOC);
break;
case MAX17050_DesignCap: //Charge full design.
case MAX17050_DesignCap: // Charge full design.
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_DesignCap);
data = data * 5 / 10;
*value = data;
break;
case MAX17050_FullCAP: //Charge full.
case MAX17050_FullCAP: // Charge full.
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_FullCAP);
data = data * 5 / 10;
*value = data;
break;
case MAX17050_RepCap: //Charge now.
case MAX17050_RepCap: // Charge now.
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RepCap);
data = data * 5 / 10;
*value = data;
break;
case MAX17050_TEMP: //Temp.
case MAX17050_TEMP: // Temp.
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_TEMP);
*value = (s16)data;
*value = *value * 10 / 256;
break;
case MAX17050_Current: //Current now.
case MAX17050_Current: // Current now.
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_Current);
*value = (s16)data;
*value *= 1562500 / MAX17050_DEFAULT_SNS_RESISTOR;
break;
case MAX17050_AvgCurrent: //Current avg.
case MAX17050_AvgCurrent: // Current avg.
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_AvgCurrent);
*value = (s16)data;
*value *= 1562500 / MAX17050_DEFAULT_SNS_RESISTOR;
@@ -125,10 +125,12 @@ static int _max17050_write_verify_reg(u8 reg, u16 value)
int ret;
u16 read_value;
do {
do
{
ret = i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, reg, (u8 *)&value, 2);
i2c_recv_buf_small((u8 *)&read_value, 2, I2C_1, MAXIM17050_I2C_ADDR, reg);
if (read_value != value) {
if (read_value != value)
{
ret = -1;
retries--;
}
@@ -152,7 +154,6 @@ static void _max17050_load_new_capacity_params()
dp_acc = 0x5e09; // =||=
repSoc = 0x6400; // 100%.
_max17050_write_verify_reg(MAX17050_RemCap, fullcap);
_max17050_write_verify_reg(MAX17050_RepCap, fullcap);
@@ -182,7 +183,7 @@ static void _max17050_reset_vfsoc0_reg()
static void _max17050_update_capacity_regs()
{
u16 value = 0x2476; //Set to 4667mAh design capacity.
u16 value = 0x2476; // Set to 4667mAh design capacity.
_max17050_write_verify_reg(MAX17050_FullCAP, value);
_max17050_write_verify_reg(MAX17050_FullCAPNom, value);
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_DesignCap, config->design_cap, 2);
@@ -210,7 +211,7 @@ static void _max17050_override_por_values()
{
u16 dq_acc = 0x10bc; // From a healthy fuel gauge.
u16 dp_acc = 0x5e09; // =||=
_max17050_override_por(MAX17050_dQacc, dq_acc);
_max17050_override_por(MAX17050_dPacc, dp_acc);
@@ -218,7 +219,7 @@ static void _max17050_override_por_values()
//_max17050_override_por(MAX17050_TempCo, config->tcompc0); //0x1b22
//u16 k_empty0 = 0x439;
//_max17050_override_por(map, MAX17050_K_empty0, k_empty0); // unknown cell data
//_max17050_override_por(map, MAX17050_K_empty0, k_empty0); // Unknown cell data
}
static void _max17050_set_por_bit(u16 value)
@@ -241,7 +242,6 @@ int max17050_fix_configuration()
/* Initialize configaration */
_max17050_write_config_regs();
/* update capacity params */
_max17050_update_capacity_regs();

2
ipl/max77620.h → bootloader/power/max77620.h Executable file → Normal file
View File

@@ -11,6 +11,8 @@
#ifndef _MFD_MAX77620_H_
#define _MFD_MAX77620_H_
#define MAX77620_I2C_ADDR 0x3C
/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */
#define MAX77620_REG_CNFGGLBL1 0x00
#define MAX77620_REG_CNFGGLBL2 0x01

58
ipl/max7762x.c → bootloader/power/max7762x.c Executable file → Normal file
View File

@@ -1,28 +1,23 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 "max7762x.h"
#include "max77620.h"
#include "i2c.h"
#include "util.h"
#include "gfx.h"
extern gfx_ctxt_t gfx_ctxt;
extern gfx_con_t gfx_con;
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
#include "../soc/i2c.h"
#include "../utils/util.h"
#define REGULATOR_SD 0
#define REGULATOR_LDO 1
@@ -73,8 +68,8 @@ int max77620_regulator_get_status(u32 id)
const max77620_regulator_t *reg = &_pmic_regulators[id];
if (reg->type == REGULATOR_SD)
return (i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1;
return (i2c_recv_byte(I2C_5, 0x3C, reg->cfg_addr) & 8) ? 1 : 0;
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1;
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & 8) ? 1 : 0;
}
int max77620_regulator_config_fps(u32 id)
@@ -84,7 +79,7 @@ int max77620_regulator_config_fps(u32 id)
const max77620_regulator_t *reg = &_pmic_regulators[id];
i2c_send_byte(I2C_5, 0x3C, reg->fps_addr, (reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period));
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg->fps_addr, (reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period));
return 1;
}
@@ -100,9 +95,9 @@ int max77620_regulator_set_voltage(u32 id, u32 mv)
return 0;
u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
u8 val = i2c_recv_byte(I2C_5, 0x3C, reg->volt_addr);
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr);
val = (val & ~reg->volt_mask) | (mult & reg->volt_mask);
i2c_send_byte(I2C_5, 0x3C, reg->volt_addr, val);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr, val);
usleep(1000);
return 1;
@@ -116,12 +111,12 @@ int max77620_regulator_enable(u32 id, int enable)
const max77620_regulator_t *reg = &_pmic_regulators[id];
u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr;
u8 val = i2c_recv_byte(I2C_5, 0x3C, addr);
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, addr);
if (enable)
val = (val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask);
else
val &= ~reg->enable_mask;
i2c_send_byte(I2C_5, 0x3C, addr, val);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, addr, val);
usleep(1000);
return 1;
@@ -131,16 +126,17 @@ void max77620_config_default()
{
for (u32 i = 1; i <= REGULATOR_MAX; i++)
{
i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_CID4);
i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4);
max77620_regulator_config_fps(i);
max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default);
if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE)
max77620_regulator_enable(i, 1);
}
i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_SD_CFG2, 4);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 4);
}
void max77620_low_battery_monitor_config()
{
i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_CNFGGLBL1, MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1,
MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N);
}

114
bootloader/power/max7762x.h Normal file
View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _MAX7762X_H_
#define _MAX7762X_H_
#include "../utils/types.h"
/*
* Switch Power domains (max77620):
* Name | Usage | uV step | uV min | uV default | uV max | Init
*-------+---------------+---------+--------+------------+---------+------------------
* sd0 | core | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1)
* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1)
* sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv)
* sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 |
* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1)
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
* ldo3 | | 50000 | 800000 | 3100000 | 3100000 |
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 |
* ldo5 | | 50000 | 800000 | 1800000 | 1800000 |
* ldo6 | | 50000 | 800000 | 2900000 | 2900000 |
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 |
* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 |
*/
/*
* MAX77620_AME_GPIO: control GPIO modes (bits 0 - 7 correspond to GPIO0 - GPIO7); 0 -> GPIO, 1 -> alt-mode
* MAX77620_REG_GPIOx: 0x9 sets output and enable
*/
/*! MAX77620 partitions. */
#define REGULATOR_SD0 0
#define REGULATOR_SD1 1
#define REGULATOR_SD2 2
#define REGULATOR_SD3 3
#define REGULATOR_LDO0 4
#define REGULATOR_LDO1 5
#define REGULATOR_LDO2 6
#define REGULATOR_LDO3 7
#define REGULATOR_LDO4 8
#define REGULATOR_LDO5 9
#define REGULATOR_LDO6 10
#define REGULATOR_LDO7 11
#define REGULATOR_LDO8 12
#define REGULATOR_MAX 12
#define MAX77621_CPU_I2C_ADDR 0x1B
#define MAX77621_GPU_I2C_ADDR 0x1C
#define MAX77621_VOUT_REG 0
#define MAX77621_VOUT_DVC_REG 1
#define MAX77621_CONTROL1_REG 2
#define MAX77621_CONTROL2_REG 3
/* MAX77621_VOUT */
#define MAX77621_VOUT_ENABLE (1 << 7)
#define MAX77621_VOUT_MASK 0x7F
/* MAX77621_VOUT_DVC_DVS */
#define MAX77621_DVS_VOUT_MASK 0x7F
/* MAX77621_CONTROL1 */
#define MAX77621_SNS_ENABLE (1 << 7)
#define MAX77621_FPWM_EN_M (1 << 6)
#define MAX77621_NFSR_ENABLE (1 << 5)
#define MAX77621_AD_ENABLE (1 << 4)
#define MAX77621_BIAS_ENABLE (1 << 3)
#define MAX77621_FREQSHIFT_9PER (1 << 2)
#define MAX77621_RAMP_12mV_PER_US 0x0
#define MAX77621_RAMP_25mV_PER_US 0x1
#define MAX77621_RAMP_50mV_PER_US 0x2
#define MAX77621_RAMP_200mV_PER_US 0x3
#define MAX77621_RAMP_MASK 0x3
/* MAX77621_CONTROL2 */
#define MAX77621_WDTMR_ENABLE (1 << 6)
#define MAX77621_DISCH_ENBABLE (1 << 5)
#define MAX77621_FT_ENABLE (1 << 4)
#define MAX77621_T_JUNCTION_120 (1 << 7)
#define MAX77621_CKKADV_TRIP_DISABLE 0xC
#define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0
#define MAX77621_CKKADV_TRIP_150mV_PER_US 0x4
#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8
#define MAX77621_INDUCTOR_MIN_30_PER 0x0
#define MAX77621_INDUCTOR_NOMINAL 0x1
#define MAX77621_INDUCTOR_PLUS_30_PER 0x2
#define MAX77621_INDUCTOR_PLUS_60_PER 0x3
int max77620_regulator_get_status(u32 id);
int max77620_regulator_config_fps(u32 id);
int max77620_regulator_set_voltage(u32 id, u32 mv);
int max77620_regulator_enable(u32 id, int enable);
void max77620_config_default();
void max77620_low_battery_monitor_config();
#endif

34
bootloader/reloc.S Normal file
View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
/*
* TODO: the placement of the relocator is a bit fragile atm, maybe we
* should include it in start.S and copy it to some known good
* place in IRAM instead. Basically we want it as far back atm
* as it might be overwritten during relocation.
*/
.section .text.reloc
.arm
.globl _reloc_ipl
.type _reloc_ipl, %function
_reloc_ipl:
LDMIA R0!, {R4-R7}
STMIA R1!, {R4-R7}
SUBS R2, #0x10
BNE _reloc_ipl
BX R3

48
ipl/se.c → bootloader/sec/se.c Executable file → Normal file
View File

@@ -1,27 +1,28 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018 Atmosphère-NX
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018 Atmosphère-NX
*
* 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 "se.h"
#include "heap.h"
#include "t210.h"
#include "se_t210.h"
#include "util.h"
#include "../sec/se.h"
#include "../mem/heap.h"
#include "../soc/t210.h"
#include "../sec/se_t210.h"
#include "../utils/util.h"
typedef struct _se_ll_t
{
@@ -104,6 +105,9 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
{
if (!src || !dst)
return 0;
u8 *block = (u8 *)malloc(0x10);
memset(block, 0, 0x10);
@@ -163,7 +167,9 @@ int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
return _se_execute(OP_START, NULL, 0, input, 0x10);
}

2
ipl/se.h → bootloader/sec/se.h Executable file → Normal file
View File

@@ -17,7 +17,7 @@
#ifndef _SE_H_
#define _SE_H_
#include "types.h"
#include "../utils/types.h"
void se_rsa_acc_ctrl(u32 rs, u32 flags);
void se_key_acc_ctrl(u32 ks, u32 flags);

2
ipl/se_t210.h → bootloader/sec/se_t210.h Executable file → Normal file
View File

@@ -21,7 +21,7 @@
#ifndef _CRYPTO_TEGRA_SE_H
#define _CRYPTO_TEGRA_SE_H
#include "types.h"
#include "../utils/types.h"
#define TEGRA_SE_CRA_PRIORITY 300
#define TEGRA_SE_COMPOSITE_PRIORITY 400

39
ipl/tsec.c → bootloader/sec/tsec.c Executable file → Normal file
View File

@@ -1,25 +1,26 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 "tsec.h"
#include "clock.h"
#include "t210.h"
#include "heap.h"
#include "util.h"
#include "../sec/tsec.h"
#include "../soc/clock.h"
#include "../soc/t210.h"
#include "../mem/heap.h"
#include "../utils/util.h"
static int _tsec_dma_wait_idle()
{

2
ipl/tsec.h → bootloader/sec/tsec.h Executable file → Normal file
View File

@@ -17,7 +17,7 @@
#ifndef _TSEC_H_
#define _TSEC_H_
#include "types.h"
#include "../utils/types.h"
int tsec_query(u8 *dst, u32 rev, void *fw);

140
ipl/clock.c → bootloader/soc/clock.c Executable file → Normal file
View File

@@ -1,25 +1,25 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 "clock.h"
#include "t210.h"
#include "util.h"
#include "sdmmc.h"
#include "../soc/clock.h"
#include "../soc/t210.h"
#include "../utils/util.h"
#include "../storage/sdmmc.h"
static const clock_t _clock_uart[] = {
static const clock_t _clock_uart[] = {
/* UART A */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, 6, 0, 0 },
/* UART B */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, 7, 0, 0 },
/* UART C */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, 0x17, 0, 0 },
@@ -36,7 +36,8 @@ static const clock_t _clock_i2c[] = {
/* I2C6 */ { 0 }
};
static clock_t _clock_se = { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, 0x42C, 0x1F, 0, 0 };
static clock_t _clock_se = { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, 0x1F, 0, 0 };
static clock_t _clock_unk2 = { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_RST_SOURCE, 0x1E, 0, 0 };
static clock_t _clock_host1x = { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, 0x1C, 4, 3 };
static clock_t _clock_tsec = { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, 0x13, 0, 2 };
@@ -48,30 +49,32 @@ static clock_t _clock_kfuse = { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTRO
static clock_t _clock_cl_dvfs = { CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_RST_CONTROLLER_RST_SOURCE, 0x1B, 0, 0 };
static clock_t _clock_coresight = { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, 9, 0, 4};
static clock_t _clock_pwm = { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, 0x11, 6, 4};
void clock_enable(const clock_t *clk)
{
//Put clock into reset.
// Put clock into reset.
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~(1 << clk->index)) | (1 << clk->index);
//Disable.
// Disable.
CLOCK(clk->enable) &= ~(1 << clk->index);
//Configure clock source if required.
// Configure clock source if required.
if (clk->source)
CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29);
//Enable.
// Enable.
CLOCK(clk->enable) = (CLOCK(clk->enable) & ~(1 << clk->index)) | (1 << clk->index);
//Take clock off reset.
// Take clock off reset.
CLOCK(clk->reset) &= ~(1 << clk->index);
}
void clock_disable(const clock_t *clk)
{
//Put clock into reset.
// Put clock into reset.
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~(1 << clk->index)) | (1 << clk->index);
//Disable.
// Disable.
CLOCK(clk->enable) &= ~(1 << clk->index);
}
void clock_enable_fuse(u32 enable)
void clock_enable_fuse(bool enable)
{
CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) = (CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) & 0xEFFFFFFF) | ((enable & 1) << 28);
}
@@ -86,11 +89,21 @@ void clock_enable_i2c(u32 idx)
clock_enable(&_clock_i2c[idx]);
}
void clock_disable_i2c(u32 idx)
{
clock_disable(&_clock_i2c[idx]);
}
void clock_enable_se()
{
clock_enable(&_clock_se);
}
void clock_enable_unk2()
{
clock_enable(&_clock_unk2);
}
void clock_enable_host1x()
{
clock_enable(&_clock_host1x);
@@ -162,40 +175,60 @@ void clock_enable_cl_dvfs()
clock_enable(&_clock_cl_dvfs);
}
void clock_disable_cl_dvfs()
{
clock_disable(&_clock_cl_dvfs);
}
void clock_enable_coresight()
{
clock_enable(&_clock_coresight);
}
#define L_SWR_SDMMC1_RST (1<<14)
#define L_SWR_SDMMC2_RST (1<<9)
#define L_SWR_SDMMC4_RST (1<<15)
#define U_SWR_SDMMC3_RST (1<<5)
void clock_disable_coresight()
{
clock_disable(&_clock_coresight);
}
#define L_CLK_ENB_SDMMC1 (1<<14)
#define L_CLK_ENB_SDMMC2 (1<<9)
#define L_CLK_ENB_SDMMC4 (1<<15)
#define U_CLK_ENB_SDMMC3 (1<<5)
void clock_enable_pwm()
{
clock_enable(&_clock_pwm);
}
#define L_SET_SDMMC1_RST (1<<14)
#define L_SET_SDMMC2_RST (1<<9)
#define L_SET_SDMMC4_RST (1<<15)
#define U_SET_SDMMC3_RST (1<<5)
void clock_disable_pwm()
{
clock_disable(&_clock_pwm);
}
#define L_CLR_SDMMC1_RST (1<<14)
#define L_CLR_SDMMC2_RST (1<<9)
#define L_CLR_SDMMC4_RST (1<<15)
#define U_CLR_SDMMC3_RST (1<<5)
#define L_SWR_SDMMC1_RST (1 << 14)
#define L_SWR_SDMMC2_RST (1 << 9)
#define L_SWR_SDMMC4_RST (1 << 15)
#define U_SWR_SDMMC3_RST (1 << 5)
#define L_SET_CLK_ENB_SDMMC1 (1<<14)
#define L_SET_CLK_ENB_SDMMC2 (1<<9)
#define L_SET_CLK_ENB_SDMMC4 (1<<15)
#define U_SET_CLK_ENB_SDMMC3 (1<<5)
#define L_CLK_ENB_SDMMC1 (1 << 14)
#define L_CLK_ENB_SDMMC2 (1 << 9)
#define L_CLK_ENB_SDMMC4 (1 << 15)
#define U_CLK_ENB_SDMMC3 (1 << 5)
#define L_CLR_CLK_ENB_SDMMC1 (1<<14)
#define L_CLR_CLK_ENB_SDMMC2 (1<<9)
#define L_CLR_CLK_ENB_SDMMC4 (1<<15)
#define U_CLR_CLK_ENB_SDMMC3 (1<<5)
#define L_SET_SDMMC1_RST (1 << 14)
#define L_SET_SDMMC2_RST (1 << 9)
#define L_SET_SDMMC4_RST (1 << 15)
#define U_SET_SDMMC3_RST (1 << 5)
#define L_CLR_SDMMC1_RST (1 << 14)
#define L_CLR_SDMMC2_RST (1 << 9)
#define L_CLR_SDMMC4_RST (1 << 15)
#define U_CLR_SDMMC3_RST (1 << 5)
#define L_SET_CLK_ENB_SDMMC1 (1 << 14)
#define L_SET_CLK_ENB_SDMMC2 (1 << 9)
#define L_SET_CLK_ENB_SDMMC4 (1 << 15)
#define U_SET_CLK_ENB_SDMMC3 (1 << 5)
#define L_CLR_CLK_ENB_SDMMC1 (1 << 14)
#define L_CLR_CLK_ENB_SDMMC2 (1 << 9)
#define L_CLR_CLK_ENB_SDMMC4 (1 << 15)
#define U_CLR_CLK_ENB_SDMMC3 (1 << 5)
static int _clock_sdmmc_is_reset(u32 id)
{
@@ -331,7 +364,8 @@ static int _clock_sdmmc_config_clock_source_inner(u32 *pout, u32 id, u32 val)
divisor = 2;
break;
default:
return 0;
*pout = 24728;
divisor = 31;
}
_clock_sdmmc_table[2 * id] = val;

46
ipl/clock.h → bootloader/soc/clock.h Executable file → Normal file
View File

@@ -1,23 +1,23 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 _CLOCK_H_
#define _CLOCK_H_
#include "types.h"
#include "../utils/types.h"
/*! Clock registers. */
#define CLK_RST_CONTROLLER_RST_SOURCE 0x0
@@ -34,6 +34,7 @@
#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30
#define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48
#define CLK_RST_CONTROLLER_OSC_CTRL 0x50
#define CLK_RST_CONTROLLER_PLLC_BASE 0x80
#define CLK_RST_CONTROLLER_PLLC_MISC 0x88
#define CLK_RST_CONTROLLER_PLLM_BASE 0x90
#define CLK_RST_CONTROLLER_PLLM_MISC1 0x98
@@ -42,8 +43,11 @@
#define CLK_RST_CONTROLLER_PLLD_BASE 0xD0
#define CLK_RST_CONTROLLER_PLLX_BASE 0xE0
#define CLK_RST_CONTROLLER_PLLX_MISC 0xE4
#define CLK_RST_CONTROLLER_PLLE_BASE 0xE8
#define CLK_RST_CONTROLLER_PLLE_MISC 0xEC
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA 0xF8
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB 0xFC
#define CLK_RST_CONTROLLER_CLK_SOURCE_PWM 0x110
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 0x124
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 0x128
#define CLK_RST_CONTROLLER_CLK_SOURCE_VI 0x148
@@ -54,6 +58,7 @@
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB 0x17C
#define CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X 0x180
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC 0x1A0
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C3 0x1B8
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 0x1BC
#define CLK_RST_CONTROLLER_CLK_SOURCE_CSITE 0x1D4
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC 0x19C
@@ -91,11 +96,14 @@
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD 0x3A4
#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT 0x3B4
#define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 0x410
#define CLK_RST_CONTROLLER_CLK_SOURCE_SE 0x42C
#define CLK_RST_CONTROLLER_CLK_ENB_V_SET 0x440
#define CLK_RST_CONTROLLER_CLK_ENB_W_SET 0x448
#define CLK_RST_CONTROLLER_CLK_ENB_W_CLR 0x44C
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET 0x450
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR 0x454
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG2 0x488
#define CLK_RST_CONTROLLER_PLLE_AUX 0x48C
#define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S0 0x4A0
#define CLK_RST_CONTROLLER_PLLX_MISC_3 0x518
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE 0x554
@@ -124,10 +132,12 @@ void clock_enable(const clock_t *clk);
void clock_disable(const clock_t *clk);
/*! Clock control for specific hardware portions. */
void clock_enable_fuse(u32 enable);
void clock_enable_fuse(bool enable);
void clock_enable_uart(u32 idx);
void clock_enable_i2c(u32 idx);
void clock_disable_i2c(u32 idx);
void clock_enable_se();
void clock_enable_unk2();
void clock_enable_host1x();
void clock_disable_host1x();
void clock_enable_tsec();
@@ -141,7 +151,11 @@ void clock_disable_sor1();
void clock_enable_kfuse();
void clock_disable_kfuse();
void clock_enable_cl_dvfs();
void clock_disable_cl_dvfs();
void clock_enable_coresight();
void clock_disable_coresight();
void clock_enable_pwm();
void clock_disable_pwm();
void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val);
void clock_sdmmc_get_params(u32 *pout, u16 *pdivisor, u32 type);
int clock_sdmmc_is_not_reset_and_enabled(u32 id);

130
bootloader/soc/cluster.c Normal file
View File

@@ -0,0 +1,130 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 "../soc/cluster.h"
#include "../soc/i2c.h"
#include "../soc/clock.h"
#include "../utils/util.h"
#include "../soc/pmc.h"
#include "../soc/t210.h"
#include "../power/max77620.h"
#include "../power/max7762x.h"
void _cluster_enable_power()
{
u8 tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, tmp & 0xDF);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH);
// Enable cores power.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG,
MAX77621_AD_ENABLE | MAX77621_NFSR_ENABLE | MAX77621_SNS_ENABLE); // 1-3.x: MAX77621_NFSR_ENABLE
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
MAX77621_T_JUNCTION_120 | MAX77621_WDTMR_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US| MAX77621_INDUCTOR_NOMINAL); // 1-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_ENABLE | 0x37);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVC_REG, MAX77621_VOUT_ENABLE | 0x37);
}
int _cluster_pmc_enable_partition(u32 part, u32 toggle, bool enable)
{
// Check if the partition has already been turned on.
if (enable && PMC(APBDEV_PMC_PWRGATE_STATUS) & part)
return 1;
u32 i = 5001;
while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & 0x100)
{
usleep(1);
i--;
if (i < 1)
return 0;
}
PMC(APBDEV_PMC_PWRGATE_TOGGLE) = toggle | (enable ? 0x100 : 0);
i = 5001;
while (i > 0)
{
if (PMC(APBDEV_PMC_PWRGATE_STATUS) & part)
break;
usleep(1);
i--;
}
return 1;
}
void cluster_boot_cpu0(u32 entry)
{
// Set ACTIVE_CLUSER to FAST.
FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= 0xFFFFFFFE;
_cluster_enable_power();
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000))
{
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7;
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02;
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02;
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) = (CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF) | 0x40000;
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02;
}
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000))
;
// Configure MSELECT source and enable clock.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6;
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & 0xFFFFFFF7) | 8;
// Configure initial CPU clock frequency and enable clock.
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888;
CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = 1;
clock_enable_coresight();
// CAR2PMC_CPU_ACK_WIDTH should be set to 0.
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000;
// Enable CPU rail.
_cluster_pmc_enable_partition(1, 0, true);
// Enable cluster 0 non-CPU.
_cluster_pmc_enable_partition(0x8000, 15, true);
// Enable CE0.
_cluster_pmc_enable_partition(0x4000, 14, true);
// Request and wait for RAM repair.
FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1;
while (!(FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) & 2))
;
EXCP_VEC(0x100) = 0;
// Set reset vector.
SB(SB_AA64_RESET_LOW) = entry | 1;
SB(SB_AA64_RESET_HIGH) = 0;
// Non-secure reset vector write disable.
SB(SB_CSR) = 2;
(void)SB(SB_CSR);
// Clear MSELECT reset.
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= 0xFFFFFFF7;
// Clear NONCPU reset.
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000;
// Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset.
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x411F000F;
}

37
bootloader/soc/cluster.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _CLUSTER_H_
#define _CLUSTER_H_
#include "../utils/types.h"
/*! Flow controller registers. */
#define LOW_CTLR_HALT_CPU0_EVENTS 0x0
#define LOW_CTLR_HALT_CPU1_EVENTS 0x14
#define LOW_CTLR_HALT_CPU2_EVENTS 0x1C
#define LOW_CTLR_HALT_CPU3_EVENTS 0x24
#define FLOW_CTLR_HALT_COP_EVENTS 0x4
#define FLOW_CTLR_CPU0_CSR 0x8
#define FLOW_CTLR_CPU1_CSR 0x18
#define FLOW_CTLR_CPU2_CSR 0x20
#define FLOW_CTLR_CPU3_CSR 0x28
#define FLOW_CTLR_RAM_REPAIR 0x40
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98
void cluster_boot_cpu0(u32 entry);
#endif

325
bootloader/soc/fuse.c Normal file
View File

@@ -0,0 +1,325 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011
*
* 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 "../soc/fuse.h"
#include "../soc/t210.h"
#define ARRAYSIZE(x) (sizeof(x) / sizeof(*x))
static const u32 evp_thunk_template[] = {
0xe92d0007, // STMFD SP!, {R0-R2}
0xe1a0200e, // MOV R2, LR
0xe2422002, // SUB R2, R2, #2
0xe5922000, // LDR R2, [R2]
0xe20220ff, // AND R2, R2, #0xFF
0xe1a02082, // MOV R2, R2,LSL#1
0xe59f001c, // LDR R0, =evp_thunk_template
0xe59f101c, // LDR R1, =thunk_end
0xe0411000, // SUB R1, R1, R0
0xe59f0018, // LDR R0, =iram_evp_thunks
0xe0800001, // ADD R0, R0, R1
0xe0822000, // ADD R2, R2, R0
0xe3822001, // ORR R2, R2, #1
0xe8bd0003, // LDMFD SP!, {R0,R1}
0xe12fff12, // BX R2
0x001007b0, // off_1007EC DCD evp_thunk_template
0x001007f8, // off_1007F0 DCD thunk_end
0x40004c30, // off_1007F4 DCD iram_evp_thunks
// thunk_end is here
};
static const u32 evp_thunk_template_len = sizeof(evp_thunk_template);
// treated as 12bit values
static const u32 hash_vals[] = {1, 2, 4, 8, 0, 3, 5, 6, 7, 9, 10, 11};
void fuse_disable_program()
{
FUSE(FUSE_DISABLEREGPROGRAM) = 1;
}
u32 fuse_read_odm(u32 idx)
{
return FUSE(FUSE_RESERVED_ODMX(idx));
}
void fuse_wait_idle()
{
u32 ctrl;
do
{
ctrl = FUSE(FUSE_CTRL);
} while (((ctrl >> 16) & 0x1f) != 4);
}
u32 parity32_even(u32 *words, u32 count)
{
u32 acc = words[0];
for (u32 i = 1; i < count; i++)
{
acc ^= words[i];
}
u32 lo = ((acc & 0xffff) ^ (acc >> 16)) & 0xff;
u32 hi = ((acc & 0xffff) ^ (acc >> 16)) >> 8;
u32 x = hi ^ lo;
lo = ((x & 0xf) ^ (x >> 4)) & 3;
hi = ((x & 0xf) ^ (x >> 4)) >> 2;
x = hi ^ lo;
return (x & 1) ^ (x >> 1);
}
int patch_hash_one(u32 *word)
{
u32 bits20_31 = *word & 0xfff00000;
u32 parity_bit = parity32_even(&bits20_31, 1);
u32 hash = 0;
for (u32 i = 0; i < 12; i++)
{
if (*word & (1 << (20 + i)))
{
hash ^= hash_vals[i];
}
}
if (hash == 0)
{
if (parity_bit == 0)
{
return 0;
}
*word ^= 1 << 24;
return 1;
}
if (parity_bit == 0)
{
return 3;
}
for (u32 i = 0; i < ARRAYSIZE(hash_vals); i++)
{
if (hash_vals[i] == hash)
{
*word ^= 1 << (20 + i);
return 1;
}
}
return 2;
}
int patch_hash_multi(u32 *words, u32 count)
{
u32 parity_bit = parity32_even(words, count);
u32 bits0_14 = words[0] & 0x7fff;
u32 bit15 = words[0] & 0x8000;
u32 bits16_19 = words[0] & 0xf0000;
u32 hash = 0;
words[0] = bits16_19;
for (u32 i = 0; i < count; i++)
{
u32 w = words[i];
if (w)
{
for (u32 bitpos = 0; bitpos < 32; bitpos++)
{
if ((w >> bitpos) & 1)
{
hash ^= 0x4000 + i * 32 + bitpos;
}
}
}
}
hash ^= bits0_14;
// stupid but this is what original code does.
// equivalent to original words[0] &= 0xfff00000
words[0] = bits16_19 ^ bit15 ^ bits0_14;
if (hash == 0)
{
if (parity_bit == 0)
{
return 0;
}
words[0] ^= 0x8000;
return 1;
}
if (parity_bit == 0)
{
return 3;
}
u32 bitcount = hash - 0x4000;
if (bitcount < 16 || bitcount >= count * 32)
{
u32 num_set = 0;
for (u32 bitpos = 0; bitpos < 15; bitpos++)
{
if ((hash >> bitpos) & 1)
{
num_set++;
}
}
if (num_set != 1)
{
return 2;
}
words[0] ^= hash;
return 1;
}
words[bitcount / 32] ^= 1 << (hash & 0x1f);
return 1;
}
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
{
u32 words[80];
u32 word_count;
u32 word_addr;
u32 word0 = 0;
u32 total_read = 0;
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
word_count &= 0x7f;
word_addr = 191;
while (word_count)
{
total_read += word_count;
if (total_read >= ARRAYSIZE(words))
{
break;
}
for (u32 i = 0; i < word_count; i++)
{
FUSE(FUSE_ADDR) = word_addr--;
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
fuse_wait_idle();
words[i] = FUSE(FUSE_RDATA);
}
word0 = words[0];
if (patch_hash_multi(words, word_count) >= 2)
{
return 1;
}
u32 ipatch_count = (words[0] >> 16) & 0xf;
if (ipatch_count)
{
for (u32 i = 0; i < ipatch_count; i++)
{
u32 word = words[i];
u32 addr = (word >> 16) * 2;
u32 data = word & 0xffff;
ipatch(addr, data);
}
}
words[0] = word0;
if ((word0 >> 25) == 0)
break;
if (patch_hash_one(&word0) >= 2)
{
return 3;
}
word_count = word0 >> 25;
}
return 0;
}
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
{
u32 words[80];
u32 word_count;
u32 word_addr;
u32 word0 = 0;
u32 total_read = 0;
int evp_thunk_written = 0;
void *evp_thunk_dst_addr = 0;
memset(iram_evp_thunks, 0, *iram_evp_thunks_len);
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
word_count &= 0x7f;
word_addr = 191;
while (word_count)
{
total_read += word_count;
if (total_read >= ARRAYSIZE(words))
{
break;
}
for (u32 i = 0; i < word_count; i++)
{
FUSE(FUSE_ADDR) = word_addr--;
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
fuse_wait_idle();
words[i] = FUSE(FUSE_RDATA);
}
word0 = words[0];
if (patch_hash_multi(words, word_count) >= 2)
{
return 1;
}
u32 ipatch_count = (words[0] >> 16) & 0xf;
u32 insn_count = word_count - ipatch_count - 1;
if (insn_count)
{
if (!evp_thunk_written)
{
evp_thunk_dst_addr = (void *)iram_evp_thunks;
memcpy(evp_thunk_dst_addr, (void *)evp_thunk_template, evp_thunk_template_len);
evp_thunk_dst_addr += evp_thunk_template_len;
evp_thunk_written = 1;
*iram_evp_thunks_len = evp_thunk_template_len;
//write32(TEGRA_EXCEPTION_VECTORS_BASE + 0x208, iram_evp_thunks);
}
u32 thunk_patch_len = insn_count * sizeof(u32);
memcpy(evp_thunk_dst_addr, &words[ipatch_count + 1], thunk_patch_len);
evp_thunk_dst_addr += thunk_patch_len;
*iram_evp_thunks_len += thunk_patch_len;
}
words[0] = word0;
if ((word0 >> 25) == 0)
break;
if (patch_hash_one(&word0) >= 2)
{
return 3;
}
word_count = word0 >> 25;
}
return 0;
}
void read_raw_ipatch_fuses(u32 *words)
{
for (u32 i = 0; i < 0x100; i++)
{
FUSE(FUSE_ADDR) = i;
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
fuse_wait_idle();
words[i] = FUSE(FUSE_RDATA);
}
}

57
bootloader/soc/fuse.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011
*
* 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 _FUSE_H_
#define _FUSE_H_
#include "../utils/types.h"
/*! Fuse registers. */
#define FUSE_CTRL 0x0
#define FUSE_ADDR 0x4
#define FUSE_RDATA 0x8
#define FUSE_WDATA 0xC
#define FUSE_TIME_RD1 0x10
#define FUSE_TIME_RD2 0x14
#define FUSE_TIME_PGM1 0x18
#define FUSE_TIME_PGM2 0x1C
#define FUSE_PRIV2INTFC 0x20
#define FUSE_FUSEBYPASS 0x24
#define FUSE_PRIVATEKEYDISABLE 0x28
#define FUSE_DISABLEREGPROGRAM 0x2C
#define FUSE_WRITE_ACCESS_SW 0x30
#define FUSE_PWR_GOOD_SW 0x34
#define FUSE_FIRST_BOOTROM_PATCH_SIZE 0x19c
/*! Fuse commands. */
#define FUSE_READ 0x1
#define FUSE_WRITE 0x2
#define FUSE_SENSE 0x3
#define FUSE_CMD_MASK 0x3
/*! Fuse cache registers. */
#define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x))
void fuse_disable_program();
u32 fuse_read_odm(u32 idx);
void fuse_wait_idle();
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value));
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);
void read_raw_ipatch_fuses(u32 *words);
#endif

32
ipl/gpio.c → bootloader/soc/gpio.c Executable file → Normal file
View File

@@ -1,21 +1,21 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 "gpio.h"
#include "t210.h"
#include "../soc/gpio.h"
#include "../soc/t210.h"
static const u16 _gpio_cnf[31] = {
0x000, 0x004, 0x008, 0x00C,

30
ipl/gpio.h → bootloader/soc/gpio.h Executable file → Normal file
View File

@@ -1,23 +1,23 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 _GPIO_H_
#define _GPIO_H_
#include "types.h"
#include "../utils/types.h"
#define GPIO_MODE_SPIO 0
#define GPIO_MODE_GPIO 1

143
bootloader/soc/i2c.c Normal file
View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 "i2c.h"
#include "../utils/util.h"
static u32 i2c_addrs[] = {
0x7000C000, 0x7000C400, 0x7000C500,
0x7000C700, 0x7000D000, 0x7000D100
};
static void _i2c_wait(vu32 *base)
{
base[I2C_CONFIG_LOAD] = 0x25;
for (u32 i = 0; i < 20; i++)
{
usleep(1);
if (!(base[I2C_CONFIG_LOAD] & 1))
break;
}
}
static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size)
{
if (size > 4)
return 0;
u32 tmp = 0;
memcpy(&tmp, buf, size);
vu32 *base = (vu32 *)i2c_addrs[idx];
base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode).
base[I2C_CMD_DATA1] = tmp; //Set value.
base[I2C_CNFG] = (2 * size - 2) | 0x2800; //Set size and send mode.
_i2c_wait(base); //Kick transaction.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200;
while (base[I2C_STATUS] & 0x100)
;
if (base[I2C_STATUS] << 28)
return 0;
return 1;
}
static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x)
{
if (size > 8)
return 0;
vu32 *base = (vu32 *)i2c_addrs[idx];
base[I2C_CMD_ADDR0] = (x << 1) | 1; // Set x (recv mode).
base[I2C_CNFG] = (size - 1) << 1 | 0x2840; // Set size and recv mode.
_i2c_wait(base); // Kick transaction.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200;
while (base[I2C_STATUS] & 0x100)
;
if (base[I2C_STATUS] << 28)
return 0;
u32 tmp = base[I2C_CMD_DATA1]; // Get LS value.
if (size > 4)
{
memcpy(buf, &tmp, 4);
tmp = base[I2C_CMD_DATA2]; // Get MS value.
memcpy(buf + 4, &tmp, size - 4);
}
else
memcpy(buf, &tmp, size);
return 1;
}
void i2c_init(u32 idx)
{
vu32 *base = (vu32 *)i2c_addrs[idx];
base[I2C_CLK_DIVISOR_REGISTER] = 0x50001;
base[I2C_BUS_CLEAR_CONFIG] = 0x90003;
_i2c_wait(base);
for (u32 i = 0; i < 10; i++)
{
usleep(20000);
if (base[INTERRUPT_STATUS_REGISTER] & 0x800)
break;
}
(vu32)base[I2C_BUS_CLEAR_STATUS];
base[INTERRUPT_STATUS_REGISTER] = base[INTERRUPT_STATUS_REGISTER];
}
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size)
{
u8 tmp[4];
if (size > 3)
return 0;
tmp[0] = y;
memcpy(tmp + 1, buf, size);
return _i2c_send_pkt(idx, x, tmp, size + 1);
}
int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y)
{
int res = _i2c_send_pkt(idx, x, (u8 *)&y, 1);
if (res)
res = _i2c_recv_pkt(idx, buf, size, x);
return res;
}
int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b)
{
return i2c_send_buf_small(idx, x, y, &b, 1);
}
u8 i2c_recv_byte(u32 idx, u32 x, u32 y)
{
u8 tmp = 0;
i2c_recv_buf_small(&tmp, 1, idx, x, y);
return tmp;
}

46
bootloader/soc/i2c.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _I2C_H_
#define _I2C_H_
#include "../utils/types.h"
#define I2C_1 0
#define I2C_2 1
#define I2C_3 2
#define I2C_4 3
#define I2C_5 4
#define I2C_6 5
#define I2C_CNFG 0x00
#define I2C_CMD_ADDR0 0x01
#define I2C_CMD_DATA1 0x03
#define I2C_CMD_DATA2 0x04
#define I2C_STATUS 0x07
#define INTERRUPT_STATUS_REGISTER 0x1A
#define I2C_CLK_DIVISOR_REGISTER 0x1B
#define I2C_BUS_CLEAR_CONFIG 0x21
#define I2C_BUS_CLEAR_STATUS 0x22
#define I2C_CONFIG_LOAD 0x23
void i2c_init(u32 idx);
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size);
int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y);
int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b);
u8 i2c_recv_byte(u32 idx, u32 x, u32 y);
#endif

42
bootloader/soc/kfuse.c Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 "../soc/kfuse.h"
#include "../soc/clock.h"
#include "../soc/t210.h"
int kfuse_read(u32 *buf)
{
int res = 0;
clock_enable_kfuse();
while (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_DONE))
;
if (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_CRCPASS))
goto out;
KFUSE(KFUSE_KEYADDR) = KFUSE_KEYADDR_AUTOINC;
for (int i = 0; i < KFUSE_NUM_WORDS; i++)
buf[i] = KFUSE(KFUSE_KEYS);
res = 1;
out:;
clock_disable_kfuse();
return res;
}

41
bootloader/soc/kfuse.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _KFUSE_H_
#define _KFUSE_H_
#include "../utils/types.h"
#define KFUSE_STATE_SOFTRESET (1 << 31)
#define KFUSE_STATE_STOP (1 << 25)
#define KFUSE_STATE_RESTART (1 << 24)
#define KFUSE_STATE_CRCPASS (1 << 17)
#define KFUSE_STATE_DONE (1 << 16)
#define KFUSE_STATE_ERRBLOCK_MASK 0x3F00
#define KFUSE_STATE_ERRBLOCK_SHIFT 8
#define KFUSE_STATE_CURBLOCK_MASK 0x3F
#define KFUSE_KEYADDR_AUTOINC (1<<16)
#define KFUSE_STATE 0x80
#define KFUSE_KEYADDR 0x88
#define KFUSE_KEYS 0x8C
#define KFUSE_NUM_WORDS 144
int kfuse_read(u32 *buf);
#endif

32
bootloader/soc/pinmux.c Normal file
View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 "../soc/pinmux.h"
#include "../soc/t210.h"
void pinmux_config_uart(u32 idx)
{
PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = 0;
PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_UARTX_RTS(idx)) = 0;
PINMUX_AUX(PINMUX_AUX_UARTX_CTS(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN;
}
void pinmux_config_i2c(u32 idx)
{
PINMUX_AUX(PINMUX_AUX_X_I2C_SCL(idx)) = PINMUX_INPUT_ENABLE;
PINMUX_AUX(PINMUX_AUX_X_I2C_SDA(idx)) = PINMUX_INPUT_ENABLE;
}

32
ipl/pinmux.h → bootloader/soc/pinmux.h Executable file → Normal file
View File

@@ -1,23 +1,23 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 _PINMUX_H_
#define _PINMUX_H_
#include "types.h"
#include "../utils/types.h"
/*! APB MISC registers. */
#define APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL 0x8D4
@@ -41,6 +41,8 @@
#define PINMUX_AUX_DMIC3_CLK 0xB4
#define PINMUX_AUX_UART2_TX 0xF4
#define PINMUX_AUX_UART3_TX 0x104
#define PINMUX_AUX_WIFI_EN 0x1B4
#define PINMUX_AUX_WIFI_RST 0x1B8
#define PINMUX_AUX_NFC_EN 0x1D0
#define PINMUX_AUX_NFC_INT 0x1D4
#define PINMUX_AUX_LCD_BL_PWM 0x1FC

60
bootloader/soc/pmc.h Normal file
View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
*
* 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 _PMC_H_
#define _PMC_H_
/*! PMC registers. */
#define APBDEV_PMC_SEC_DISABLE 0x4
#define APBDEV_PMC_PWRGATE_TOGGLE 0x30
#define APBDEV_PMC_PWRGATE_STATUS 0x38
#define APBDEV_PMC_NO_IOPOWER 0x44
#define APBDEV_PMC_SCRATCH0 0x50
#define APBDEV_PMC_SCRATCH1 0x54
#define APBDEV_PMC_SCRATCH20 0xA0
#define APBDEV_PMC_PWR_DET_VAL 0xE4
#define APBDEV_PMC_DDR_PWR 0xE8
#define APBDEV_PMC_CRYPTO_OP 0xF4
#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4
#define APBDEV_PMC_RST_STATUS 0x1B4
#define APBDEV_PMC_IO_DPD_REQ 0x1B8
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0
#define APBDEV_PMC_VDDP_SEL 0x1CC
#define APBDEV_PMC_SCRATCH49 0x244
#define APBDEV_PMC_TSC_MULT 0x2B4
#define APBDEV_PMC_SEC_DISABLE2 0x2C4
#define APBDEV_PMC_WEAK_BIAS 0x2C8
#define APBDEV_PMC_REG_SHORT 0x2CC
#define APBDEV_PMC_SEC_DISABLE3 0x2D8
#define APBDEV_PMC_SECURE_SCRATCH21 0x334
#define APBDEV_PMC_SECURE_SCRATCH32 0x360
#define APBDEV_PMC_SECURE_SCRATCH49 0x3A4
#define APBDEV_PMC_CNTRL2 0x440
#define APBDEV_PMC_IO_DPD4_REQ 0x464
#define APBDEV_PMC_UTMIP_PAD_CFG1 0x4C4
#define APBDEV_PMC_UTMIP_PAD_CFG3 0x4CC
#define APBDEV_PMC_DDR_CNTRL 0x4E4
#define APBDEV_PMC_SEC_DISABLE4 0x5B0
#define APBDEV_PMC_SEC_DISABLE5 0x5B4
#define APBDEV_PMC_SEC_DISABLE6 0x5B8
#define APBDEV_PMC_SEC_DISABLE7 0x5BC
#define APBDEV_PMC_SEC_DISABLE8 0x5C0
#define APBDEV_PMC_SCRATCH188 0x810
#define APBDEV_PMC_SCRATCH190 0x818
#define APBDEV_PMC_SCRATCH200 0x840
#endif

View File

@@ -0,0 +1,564 @@
/*
* Copyright (c) 2010-2015, NVIDIA CORPORATION. All rights reserved.
*
* 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.
*/
#ifndef _TEGRA210_PMC_H_
#define _TEGRA210_PMC_H_
#include "../utils/types.h"
struct tegra_pmc_regs
{
u32 cntrl;
u32 sec_disable;
u32 pmc_swrst;
u32 wake_mask;
u32 wake_lvl;
u32 wake_status;
u32 sw_wake_status;
u32 dpd_pads_oride;
u32 dpd_sample;
u32 dpd_enable;
u32 pwrgate_timer_off;
u32 clamp_status;
u32 pwrgate_toggle;
u32 remove_clamping_cmd;
u32 pwrgate_status;
u32 pwrgood_timer;
u32 blink_timer;
u32 no_iopower;
u32 pwr_det;
u32 pwr_det_latch;
u32 scratch0;
u32 scratch1;
u32 scratch2;
u32 scratch3;
u32 scratch4;
u32 scratch5;
u32 scratch6;
u32 scratch7;
u32 scratch8;
u32 scratch9;
u32 scratch10;
u32 scratch11;
u32 scratch12;
u32 scratch13;
u32 scratch14;
u32 scratch15;
u32 scratch16;
u32 scratch17;
u32 scratch18;
u32 scratch19;
u32 odmdata;
u32 scratch21;
u32 scratch22;
u32 scratch23;
u32 secure_scratch0;
u32 secure_scratch1;
u32 secure_scratch2;
u32 secure_scratch3;
u32 secure_scratch4;
u32 secure_scratch5;
u32 cpupwrgood_timer;
u32 cpupwroff_timer;
u32 pg_mask;
u32 pg_mask_1;
u32 auto_wake_lvl;
u32 auto_wake_lvl_mask;
u32 wake_delay;
u32 pwr_det_val;
u32 ddr_pwr;
u32 usb_debounce_del;
u32 usb_a0;
u32 crypto_op;
u32 pllp_wb0_override;
u32 scratch24;
u32 scratch25;
u32 scratch26;
u32 scratch27;
u32 scratch28;
u32 scratch29;
u32 scratch30;
u32 scratch31;
u32 scratch32;
u32 scratch33;
u32 scratch34;
u32 scratch35;
u32 scratch36;
u32 scratch37;
u32 scratch38;
u32 scratch39;
u32 scratch40;
u32 scratch41;
u32 scratch42;
u32 bondout_mirror[3];
u32 sys_33v_en;
u32 bondout_mirror_access;
u32 gate;
u32 wake2_mask;
u32 wake2_lvl;
u32 wake2_status;
u32 sw_wake2_status;
u32 auto_wake2_lvl_mask;
u32 pg_mask_2;
u32 pg_mask_ce1;
u32 pg_mask_ce2;
u32 pg_mask_ce3;
u32 pwrgate_timer_ce[7];
u32 pcx_edpd_cntrl;
u32 osc_edpd_over;
u32 clk_out_cntrl;
u32 sata_pwrgt;
u32 sensor_ctrl;
u32 rst_status;
u32 io_dpd_req;
u32 io_dpd_status;
u32 io_dpd2_req;
u32 io_dpd2_status;
u32 sel_dpd_tim;
u32 vddp_sel;
u32 ddr_cfg;
u32 e_no_vttgen;
u8 _rsv0[4];
u32 pllm_wb0_override_freq;
u32 test_pwrgate;
u32 pwrgate_timer_mult;
u32 dis_sel_dpd;
u32 utmip_uhsic_triggers;
u32 utmip_uhsic_saved_state;
u32 utmip_pad_cfg;
u32 utmip_term_pad_cfg;
u32 utmip_uhsic_sleep_cfg;
u32 utmip_uhsic_sleepwalk_cfg;
u32 utmip_sleepwalk_p[3];
u32 uhsic_sleepwalk_p0;
u32 utmip_uhsic_status;
u32 utmip_uhsic_fake;
u32 bondout_mirror3[5 - 3];
u32 secure_scratch6;
u32 secure_scratch7;
u32 scratch43;
u32 scratch44;
u32 scratch45;
u32 scratch46;
u32 scratch47;
u32 scratch48;
u32 scratch49;
u32 scratch50;
u32 scratch51;
u32 scratch52;
u32 scratch53;
u32 scratch54;
u32 scratch55;
u32 scratch0_eco;
u32 por_dpd_ctrl;
u32 scratch2_eco;
u32 utmip_uhsic_line_wakeup;
u32 utmip_bias_master_cntrl;
u32 utmip_master_config;
u32 td_pwrgate_inter_part_timer;
u32 utmip_uhsic2_triggers;
u32 utmip_uhsic2_saved_state;
u32 utmip_uhsic2_sleep_cfg;
u32 utmip_uhsic2_sleepwalk_cfg;
u32 uhsic2_sleepwalk_p1;
u32 utmip_uhsic2_status;
u32 utmip_uhsic2_fake;
u32 utmip_uhsic2_line_wakeup;
u32 utmip_master2_config;
u32 utmip_uhsic_rpd_cfg;
u32 pg_mask_ce0;
u32 pg_mask3[5 - 3];
u32 pllm_wb0_override2;
u32 tsc_mult;
u32 cpu_vsense_override;
u32 glb_amap_cfg;
u32 sticky_bits;
u32 sec_disable2;
u32 weak_bias;
u32 reg_short;
u32 pg_mask_andor;
u8 _rsv1[0x2c];
u32 secure_scratch8; /* offset 0x300 */
u32 secure_scratch9;
u32 secure_scratch10;
u32 secure_scratch11;
u32 secure_scratch12;
u32 secure_scratch13;
u32 secure_scratch14;
u32 secure_scratch15;
u32 secure_scratch16;
u32 secure_scratch17;
u32 secure_scratch18;
u32 secure_scratch19;
u32 secure_scratch20;
u32 secure_scratch21;
u32 secure_scratch22;
u32 secure_scratch23;
u32 secure_scratch24;
u32 secure_scratch25;
u32 secure_scratch26;
u32 secure_scratch27;
u32 secure_scratch28;
u32 secure_scratch29;
u32 secure_scratch30;
u32 secure_scratch31;
u32 secure_scratch32;
u32 secure_scratch33;
u32 secure_scratch34;
u32 secure_scratch35;
u32 secure_scratch36;
u32 secure_scratch37;
u32 secure_scratch38;
u32 secure_scratch39;
u32 secure_scratch40;
u32 secure_scratch41;
u32 secure_scratch42;
u32 secure_scratch43;
u32 secure_scratch44;
u32 secure_scratch45;
u32 secure_scratch46;
u32 secure_scratch47;
u32 secure_scratch48;
u32 secure_scratch49;
u32 secure_scratch50;
u32 secure_scratch51;
u32 secure_scratch52;
u32 secure_scratch53;
u32 secure_scratch54;
u32 secure_scratch55;
u32 secure_scratch56;
u32 secure_scratch57;
u32 secure_scratch58;
u32 secure_scratch59;
u32 secure_scratch60;
u32 secure_scratch61;
u32 secure_scratch62;
u32 secure_scratch63;
u32 secure_scratch64;
u32 secure_scratch65;
u32 secure_scratch66;
u32 secure_scratch67;
u32 secure_scratch68;
u32 secure_scratch69;
u32 secure_scratch70;
u32 secure_scratch71;
u32 secure_scratch72;
u32 secure_scratch73;
u32 secure_scratch74;
u32 secure_scratch75;
u32 secure_scratch76;
u32 secure_scratch77;
u32 secure_scratch78;
u32 secure_scratch79;
u32 _rsv0x420[8];
u32 cntrl2; /* 0x440 */
u32 _rsv0x444[2];
u32 event_counter; /* 0x44C */
u32 fuse_control;
u32 scratch1_eco;
u32 _rsv0x458[1];
u32 io_dpd3_req; /* 0x45C */
u32 io_dpd3_status;
u32 io_dpd4_req;
u32 io_dpd4_status;
u32 _rsv0x46C[30];
u32 ddr_cntrl; /* 0x4E4 */
u32 _rsv0x4E8[70];
u32 scratch56; /* 0x600 */
u32 scratch57;
u32 scratch58;
u32 scratch59;
u32 scratch60;
u32 scratch61;
u32 scratch62;
u32 scratch63;
u32 scratch64;
u32 scratch65;
u32 scratch66;
u32 scratch67;
u32 scratch68;
u32 scratch69;
u32 scratch70;
u32 scratch71;
u32 scratch72;
u32 scratch73;
u32 scratch74;
u32 scratch75;
u32 scratch76;
u32 scratch77;
u32 scratch78;
u32 scratch79;
u32 scratch80;
u32 scratch81;
u32 scratch82;
u32 scratch83;
u32 scratch84;
u32 scratch85;
u32 scratch86;
u32 scratch87;
u32 scratch88;
u32 scratch89;
u32 scratch90;
u32 scratch91;
u32 scratch92;
u32 scratch93;
u32 scratch94;
u32 scratch95;
u32 scratch96;
u32 scratch97;
u32 scratch98;
u32 scratch99;
u32 scratch100;
u32 scratch101;
u32 scratch102;
u32 scratch103;
u32 scratch104;
u32 scratch105;
u32 scratch106;
u32 scratch107;
u32 scratch108;
u32 scratch109;
u32 scratch110;
u32 scratch111;
u32 scratch112;
u32 scratch113;
u32 scratch114;
u32 scratch115;
u32 scratch116;
u32 scratch117;
u32 scratch118;
u32 scratch119;
u32 scratch120; /* 0x700 */
u32 scratch121;
u32 scratch122;
u32 scratch123;
u32 scratch124;
u32 scratch125;
u32 scratch126;
u32 scratch127;
u32 scratch128;
u32 scratch129;
u32 scratch130;
u32 scratch131;
u32 scratch132;
u32 scratch133;
u32 scratch134;
u32 scratch135;
u32 scratch136;
u32 scratch137;
u32 scratch138;
u32 scratch139;
u32 scratch140;
u32 scratch141;
u32 scratch142;
u32 scratch143;
u32 scratch144;
u32 scratch145;
u32 scratch146;
u32 scratch147;
u32 scratch148;
u32 scratch149;
u32 scratch150;
u32 scratch151;
u32 scratch152;
u32 scratch153;
u32 scratch154;
u32 scratch155;
u32 scratch156;
u32 scratch157;
u32 scratch158;
u32 scratch159;
u32 scratch160;
u32 scratch161;
u32 scratch162;
u32 scratch163;
u32 scratch164;
u32 scratch165;
u32 scratch166;
u32 scratch167;
u32 scratch168;
u32 scratch169;
u32 scratch170;
u32 scratch171;
u32 scratch172;
u32 scratch173;
u32 scratch174;
u32 scratch175;
u32 scratch176;
u32 scratch177;
u32 scratch178;
u32 scratch179;
u32 scratch180;
u32 scratch181;
u32 scratch182;
u32 scratch183;
u32 scratch184;
u32 scratch185;
u32 scratch186;
u32 scratch187;
u32 scratch188;
u32 scratch189;
u32 scratch190;
u32 scratch191;
u32 scratch192;
u32 scratch193;
u32 scratch194;
u32 scratch195;
u32 scratch196;
u32 scratch197;
u32 scratch198;
u32 scratch199;
u32 scratch200;
u32 scratch201;
u32 scratch202;
u32 scratch203;
u32 scratch204;
u32 scratch205;
u32 scratch206;
u32 scratch207;
u32 scratch208;
u32 scratch209;
u32 scratch210;
u32 scratch211;
u32 scratch212;
u32 scratch213;
u32 scratch214;
u32 scratch215;
u32 scratch216;
u32 scratch217;
u32 scratch218;
u32 scratch219;
u32 scratch220;
u32 scratch221;
u32 scratch222;
u32 scratch223;
u32 scratch224;
u32 scratch225;
u32 scratch226;
u32 scratch227;
u32 scratch228;
u32 scratch229;
u32 scratch230;
u32 scratch231;
u32 scratch232;
u32 scratch233;
u32 scratch234;
u32 scratch235;
u32 scratch236;
u32 scratch237;
u32 scratch238;
u32 scratch239;
u32 scratch240;
u32 scratch241;
u32 scratch242;
u32 scratch243;
u32 scratch244;
u32 scratch245;
u32 scratch246;
u32 scratch247;
u32 scratch248;
u32 scratch249;
u32 scratch250;
u32 scratch251;
u32 scratch252;
u32 scratch253;
u32 scratch254;
u32 scratch255;
u32 scratch256;
u32 scratch257;
u32 scratch258;
u32 scratch259;
u32 scratch260;
u32 scratch261;
u32 scratch262;
u32 scratch263;
u32 scratch264;
u32 scratch265;
u32 scratch266;
u32 scratch267;
u32 scratch268;
u32 scratch269;
u32 scratch270;
u32 scratch271;
u32 scratch272;
u32 scratch273;
u32 scratch274;
u32 scratch275;
u32 scratch276;
u32 scratch277;
u32 scratch278;
u32 scratch279;
u32 scratch280;
u32 scratch281;
u32 scratch282;
u32 scratch283;
u32 scratch284;
u32 scratch285;
u32 scratch286;
u32 scratch287;
u32 scratch288;
u32 scratch289;
u32 scratch290;
u32 scratch291;
u32 scratch292;
u32 scratch293;
u32 scratch294;
u32 scratch295;
u32 scratch296;
u32 scratch297;
u32 scratch298;
u32 scratch299; /* 0x9CC */
u32 _rsv0x9D0[50];
u32 secure_scratch80; /* 0xa98 */
u32 secure_scratch81;
u32 secure_scratch82;
u32 secure_scratch83;
u32 secure_scratch84;
u32 secure_scratch85;
u32 secure_scratch86;
u32 secure_scratch87;
u32 secure_scratch88;
u32 secure_scratch89;
u32 secure_scratch90;
u32 secure_scratch91;
u32 secure_scratch92;
u32 secure_scratch93;
u32 secure_scratch94;
u32 secure_scratch95;
u32 secure_scratch96;
u32 secure_scratch97;
u32 secure_scratch98;
u32 secure_scratch99;
u32 secure_scratch100;
u32 secure_scratch101;
u32 secure_scratch102;
u32 secure_scratch103;
u32 secure_scratch104;
u32 secure_scratch105;
u32 secure_scratch106;
u32 secure_scratch107;
u32 secure_scratch108;
u32 secure_scratch109;
u32 secure_scratch110;
u32 secure_scratch111;
u32 secure_scratch112;
u32 secure_scratch113;
u32 secure_scratch114;
u32 secure_scratch115;
u32 secure_scratch116;
u32 secure_scratch117;
u32 secure_scratch118;
u32 secure_scratch119;
};
#endif /* _TEGRA210_PMC_H_ */

121
bootloader/soc/t210.h Normal file
View File

@@ -0,0 +1,121 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _T210_H_
#define _T210_H_
#include "../utils/types.h"
#define BOOTROM_BASE 0x100000
#define HOST1X_BASE 0x50000000
#define BPMP_CACHE_BASE 0x50040000
#define DISPLAY_A_BASE 0x54200000
#define DSI_BASE 0x54300000
#define VIC_BASE 0x54340000
#define TSEC_BASE 0x54500000
#define SOR1_BASE 0x54580000
#define TMR_BASE 0x60005000
#define CLOCK_BASE 0x60006000
#define FLOW_CTLR_BASE 0x60007000
#define SYSREG_BASE 0x6000C000
#define SB_BASE (SYSREG_BASE + 0x200)
#define GPIO_BASE 0x6000D000
#define GPIO_1_BASE (GPIO_BASE)
#define GPIO_2_BASE (GPIO_BASE + 0x100)
#define GPIO_3_BASE (GPIO_BASE + 0x200)
#define GPIO_4_BASE (GPIO_BASE + 0x300)
#define GPIO_5_BASE (GPIO_BASE + 0x400)
#define GPIO_6_BASE (GPIO_BASE + 0x500)
#define GPIO_7_BASE (GPIO_BASE + 0x600)
#define GPIO_8_BASE (GPIO_BASE + 0x700)
#define EXCP_VEC_BASE 0x6000F000
#define IPATCH_BASE 0x6001DC00
#define APB_MISC_BASE 0x70000000
#define PINMUX_AUX_BASE 0x70003000
#define UART_BASE 0x70006000
#define PWM_BASE 0x7000A000
#define RTC_BASE 0x7000E000
#define PMC_BASE 0x7000E400
#define SYSCTR0_BASE 0x700F0000
#define FUSE_BASE 0x7000F800
#define KFUSE_BASE 0x7000FC00
#define SE_BASE 0x70012000
#define MC_BASE 0x70019000
#define EMC_BASE 0x7001B000
#define MIPI_CAL_BASE 0x700E3000
#define I2S_BASE 0x702D1000
#define CL_DVFS_BASE 0x70110000
#define _REG(base, off) *(vu32 *)((base) + (off))
#define HOST1X(off) _REG(HOST1X_BASE, off)
#define BPMP_CACHE_CTRL(off) _REG(BPMP_CACHE_BASE, off)
#define DISPLAY_A(off) _REG(DISPLAY_A_BASE, off)
#define DSI(off) _REG(DSI_BASE, off)
#define VIC(off) _REG(VIC_BASE, off)
#define TSEC(off) _REG(TSEC_BASE, off)
#define SOR1(off) _REG(SOR1_BASE, off)
#define TMR(off) _REG(TMR_BASE, off)
#define CLOCK(off) _REG(CLOCK_BASE, off)
#define FLOW_CTLR(off) _REG(FLOW_CTLR_BASE, off)
#define SYSREG(off) _REG(SYSREG_BASE, off)
#define SB(off) _REG(SB_BASE, off)
#define GPIO(off) _REG(GPIO_BASE, off)
#define GPIO_1(off) _REG(GPIO_1_BASE, off)
#define GPIO_2(off) _REG(GPIO_2_BASE, off)
#define GPIO_3(off) _REG(GPIO_3_BASE, off)
#define GPIO_4(off) _REG(GPIO_4_BASE, off)
#define GPIO_5(off) _REG(GPIO_5_BASE, off)
#define GPIO_6(off) _REG(GPIO_6_BASE, off)
#define GPIO_7(off) _REG(GPIO_7_BASE, off)
#define GPIO_8(off) _REG(GPIO_8_BASE, off)
#define EXCP_VEC(off) _REG(EXCP_VEC_BASE, off)
#define APB_MISC(off) _REG(APB_MISC_BASE, off)
#define PINMUX_AUX(off) _REG(PINMUX_AUX_BASE, off)
#define PWM(off) _REG(PWM_BASE, off)
#define RTC(off) _REG(RTC_BASE, off)
#define PMC(off) _REG(PMC_BASE, off)
#define SYSCTR0(off) _REG(SYSCTR0_BASE, off)
#define FUSE(off) _REG(FUSE_BASE, off)
#define KFUSE(off) _REG(KFUSE_BASE, off)
#define SE(off) _REG(SE_BASE, off)
#define MC(off) _REG(MC_BASE, off)
#define EMC(off) _REG(EMC_BASE, off)
#define MIPI_CAL(off) _REG(MIPI_CAL_BASE, off)
#define I2S(off) _REG(I2S_BASE, off)
#define CL_DVFS(off) _REG(CL_DVFS_BASE, off)
#define TEST_REG(off) _REG(0x0, off)
/*! Misc registers. */
#define APB_MISC_PP_STRAPPING_OPT_A 0x08
#define APB_MISC_PP_PINMUX_GLOBAL 0x40
#define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68
/*! System registers. */
#define AHB_ARBITRATION_XBAR_CTRL 0xE0
#define AHB_AHB_SPARE_REG 0x110
/*! Secure boot registers. */
#define SB_CSR 0x0
#define SB_AA64_RESET_LOW 0x30
#define SB_AA64_RESET_HIGH 0x34
/*! SYSCTR0 registers. */
#define SYSCTR0_CNTFID0 0x20
#endif

6
ipl/uart.c → bootloader/soc/uart.c Executable file → Normal file
View File

@@ -14,9 +14,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "uart.h"
#include "t210.h"
#include "util.h"
#include "../soc/uart.h"
#include "../soc/t210.h"
#include "../utils/util.h"
/* UART A, B, C, D and E. */
static const u32 uart_baseoff[5] = { 0, 0x40, 0x200, 0x300, 0x400 };

2
ipl/uart.h → bootloader/soc/uart.h Executable file → Normal file
View File

@@ -17,7 +17,7 @@
#ifndef _UART_H_
#define _UART_H_
#include "types.h"
#include "../utils/types.h"
#define UART_A 0
#define UART_B 1

0
ipl/start.S → bootloader/start.S Executable file → Normal file
View File

42
ipl/mmc.h → bootloader/storage/mmc.h Executable file → Normal file
View File

@@ -1,25 +1,25 @@
/*
* Header for MultiMediaCard (MMC)
*
* Copyright 2002 Hewlett-Packard Company
*
* Use consistent with the GNU GPL is permitted,
* provided that this copyright notice is
* preserved in its entirety in all copies and derived works.
*
* HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* Many thanks to Alessandro Rubini and Jonathan Corbet!
*
* Based strongly on code by:
*
* Author: Yong-iL Joh <tolkien@mizi.com>
*
* Author: Andrew Christian
* 15 May 2002
*/
* Header for MultiMediaCard (MMC)
*
* Copyright 2002 Hewlett-Packard Company
*
* Use consistent with the GNU GPL is permitted,
* provided that this copyright notice is
* preserved in its entirety in all copies and derived works.
*
* HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* Many thanks to Alessandro Rubini and Jonathan Corbet!
*
* Based strongly on code by:
*
* Author: Yong-iL Joh <tolkien@mizi.com>
*
* Author: Andrew Christian
* 15 May 2002
*/
#ifndef LINUX_MMC_MMC_H
#define LINUX_MMC_MMC_H

37
ipl/nx_emmc.c → bootloader/storage/nx_emmc.c Executable file → Normal file
View File

@@ -1,23 +1,24 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 "nx_emmc.h"
#include "heap.h"
#include "list.h"
#include "../mem/heap.h"
#include "../utils/list.h"
void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
{
@@ -61,7 +62,7 @@ emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name)
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf)
{
//The last LBA is inclusive.
// The last LBA is inclusive.
if (part->lba_start + sector_off > part->lba_end)
return 0;
return sdmmc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf);
@@ -69,7 +70,7 @@ int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_of
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf)
{
//The last LBA is inclusive.
// The last LBA is inclusive.
if (part->lba_start + sector_off > part->lba_end)
return 0;
return sdmmc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf);

32
ipl/nx_emmc.h → bootloader/storage/nx_emmc.h Executable file → Normal file
View File

@@ -1,24 +1,24 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 _NX_EMMC_H_
#define _NX_EMMC_H_
#include "types.h"
#include "list.h"
#include "../utils/types.h"
#include "../utils/list.h"
#include "sdmmc.h"
typedef struct _gpt_entry_t

20
ipl/sd.h → bootloader/storage/sd.h Executable file → Normal file
View File

@@ -1,14 +1,14 @@
/*
* include/linux/mmc/sd.h
*
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (C) 2018 CTCaer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*/
* include/linux/mmc/sd.h
*
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (C) 2018 CTCaer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*/
#ifndef LINUX_MMC_SD_H
#define LINUX_MMC_SD_H

43
ipl/sdmmc.c → bootloader/storage/sdmmc.c Executable file → Normal file
View File

@@ -1,26 +1,26 @@
/*
* 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/>.
*/
* 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 <string.h>
#include "sdmmc.h"
#include "mmc.h"
#include "sd.h"
#include "util.h"
#include "heap.h"
#include "../utils/util.h"
#include "../mem/heap.h"
/*#include "gfx.h"
extern gfx_ctxt_t gfx_ctxt;
@@ -945,7 +945,8 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
if (!(storage->csd.cmdclass & CCC_APP_SPEC)) {
if (!(storage->csd.cmdclass & CCC_APP_SPEC))
{
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
return 0;
}
@@ -1084,7 +1085,11 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
u8 *buf = (u8 *)malloc(512);
if (!_sd_storage_get_scr(storage, buf))
{
free(buf);
return 0;
}
//gfx_hexdump(&gfx_con, 0, storage->raw_scr, 8);
DPRINTF("[SD] got scr\n");
@@ -1124,7 +1129,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
sdmmc_sd_clock_ctrl(sdmmc, 1);
// Parse additional card info from sd status
// Parse additional card info from sd status.
if (_sd_storage_get_ssr(storage, buf))
DPRINTF("[SD] got sd status\n");

35
ipl/sdmmc.h → bootloader/storage/sdmmc.h Executable file → Normal file
View File

@@ -1,24 +1,24 @@
/*
* 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/>.
*/
* 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 _SDMMC_H_
#define _SDMMC_H_
#include "types.h"
#include "../utils/types.h"
#include "sdmmc_driver.h"
typedef struct _mmc_cid
@@ -73,7 +73,8 @@ typedef struct _sd_scr
u8 cmds;
} sd_scr_t;
typedef struct _sd_ssr {
typedef struct _sd_ssr
{
u8 bus_width;
u8 speed_class;
u8 uhs_grade;

View File

@@ -1,31 +1,31 @@
/*
* 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/>.
*/
* 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 <string.h>
#include "sdmmc.h"
#include "util.h"
#include "clock.h"
#include "../utils/util.h"
#include "../soc/clock.h"
#include "mmc.h"
#include "max7762x.h"
#include "t210.h"
#include "pmc.h"
#include "pinmux.h"
#include "gpio.h"
#include "../power/max7762x.h"
#include "../soc/t210.h"
#include "../soc/pmc.h"
#include "../soc/pinmux.h"
#include "../soc/gpio.h"
/*#include "gfx.h"
extern gfx_ctxt_t gfx_ctxt;
@@ -190,10 +190,10 @@ out:;
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
{
//Disable the SD clock if it was enabled, and reenable it later.
int should_enable_sd_clock = 0;
bool should_enable_sd_clock = false;
if (sdmmc->regs->clkcon & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)
{
should_enable_sd_clock = 1;
should_enable_sd_clock = true;
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
}
@@ -441,7 +441,7 @@ static int _sdmmc_setup_read_small_block(sdmmc_t *sdmmc)
return 1;
}
static int _sdmmc_parse_cmdbuf(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, int is_data_present)
static int _sdmmc_parse_cmdbuf(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_present)
{
u16 cmdflags = 0;
@@ -488,7 +488,7 @@ static void _sdmmc_parse_cmd_48(sdmmc_t *sdmmc, u32 cmd)
cmdbuf.arg = 0;
cmdbuf.rsp_type = SDMMC_RSP_TYPE_1;
cmdbuf.check_busy = 0;
_sdmmc_parse_cmdbuf(sdmmc, &cmdbuf, 1);
_sdmmc_parse_cmdbuf(sdmmc, &cmdbuf, true);
}
static int _sdmmc_config_tuning_once(sdmmc_t *sdmmc, u32 cmd)
@@ -631,10 +631,10 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power)
static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
{
int should_enable_sd_clock = 0;
bool should_enable_sd_clock = false;
if (sdmmc->regs->clkcon & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)
{
should_enable_sd_clock = 1;
should_enable_sd_clock = true;
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
}
@@ -738,7 +738,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
cmd.arg = 0;
cmd.rsp_type = SDMMC_RSP_TYPE_1;
cmd.check_busy = 1;
_sdmmc_parse_cmdbuf(sdmmc, &cmd, 0);
_sdmmc_parse_cmdbuf(sdmmc, &cmd, false);
int res = _sdmmc_wait_request(sdmmc);
_sdmmc_mask_interrupts(sdmmc);
@@ -754,10 +754,10 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
if (!sdmmc->sd_clock_enabled)
return 0;
int should_disable_sd_clock = 0;
bool should_disable_sd_clock = false;
if (!(sdmmc->regs->clkcon & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE))
{
should_disable_sd_clock = 1;
should_disable_sd_clock = true;
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
_sdmmc_get_clkcon(sdmmc);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
@@ -857,17 +857,17 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
return 0;
u32 blkcnt = 0;
int is_data_present = 0;
bool is_data_present = false;
if (req)
{
_sdmmc_config_dma(sdmmc, &blkcnt, req);
_sdmmc_enable_interrupts(sdmmc);
is_data_present = 1;
is_data_present = true;
}
else
{
_sdmmc_enable_interrupts(sdmmc);
is_data_present = 0;
is_data_present = false;
}
_sdmmc_parse_cmdbuf(sdmmc, cmd, is_data_present);

View File

@@ -1,23 +1,23 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 _SDMMC_DRIVER_H_
#define _SDMMC_DRIVER_H_
#include "types.h"
#include "../utils/types.h"
#include "sdmmc_t210.h"
/*! SDMMC controller IDs. */

30
ipl/sdmmc_t210.h → bootloader/storage/sdmmc_t210.h Executable file → Normal file
View File

@@ -1,23 +1,23 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
* Copyright (c) 2018 naehrwert
*
* 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 _SDMMC_T210_H_
#define _SDMMC_T210_H_
#include "types.h"
#include "../utils/types.h"
#define TEGRA_MMC_PWRCTL_SD_BUS_POWER 0x1
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8 0xA

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 "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 _NOP() 0xD503201F
#endif

74
bootloader/utils/btn.c Normal file
View File

@@ -0,0 +1,74 @@
/*
* 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 "util.h"
#include "../power/max77620.h"
u32 btn_read()
{
u32 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(4, MAX77620_I2C_ADDR, 0x15) & 0x4)
res |= BTN_POWER;
return res;
}
u32 btn_wait()
{
u32 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;
}
u32 btn_wait_timeout(u32 time_ms, u32 mask)
{
u32 timeout = get_tmr_ms() + time_ms;
u32 res = btn_read() & mask;
do
{
if (!(res & mask))
res = btn_read() & mask;
} while (get_tmr_ms() < timeout);
return res;
}

31
bootloader/utils/btn.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* 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 "types.h"
#define BTN_POWER 0x1
#define BTN_VOL_DOWN 0x2
#define BTN_VOL_UP 0x4
u32 btn_read();
u32 btn_wait();
u32 btn_wait_timeout(u32 time_ms, u32 mask);
#endif

Some files were not shown because too many files have changed in this diff Show More