Compare commits

..

11 Commits

Author SHA1 Message Date
Kostas Missos
9be1a36e79 v2.2 (and like always, transfer unmerged PRs) 2018-06-03 09:37:37 +03:00
Kostas Missos
d4103efaa9 SD errata, bugfixes, replace hardcoded values 2018-06-03 09:07:03 +03:00
Robin Lambertz
3a0a226c4c Add SVC verification disable on 5.x 2018-06-03 01:21:34 +03:00
Kostas Missos
919bf99cb2 [HOS] Add sd unmount and proper secmon signaling 2018-06-02 00:12:22 +03:00
Kostas Missos
59d25a3be5 Oups. Remove unmerged functions 2018-06-01 19:58:25 +03:00
Kostas Missos
5796ead851 [PKG1] Move 1.0.0 secmon to 0x4002B020
So, it's time to move 1.0.0 secmon.
If we want to continue having a full featured bootloader, this change is a must.

It will move the secmon to 0x4002B000 + 0x20 (to keep the values addresses aligned).
It fixes relocator patch.

So now the payload size limit is 160KB - .bss (~158KB).
2018-06-01 19:28:22 +03:00
Kostas Missos
240e465d86 [PKG1] Add kernel patching
Add Disable Svc Verification and Debug mode.
Can be enabled via the hekate .ini

https://gist.github.com/roblabla/440f3ceaa0b2d3ca530c2a43fe258420
2018-06-01 19:22:11 +03:00
Kostas Missos
b74dde3b6d [LP0] Inform user that console halted :P
Actually this corrects sdram cfg parsing in LP0.
The cfg is missing 3 variables, which ultimately are unused in T210.

Remove them and fix LP0 configuration saving.
The console sleep, still does not work. But now it tries to enter/leave sleep and halts with backlight on.

At least, this reminds the user to power off the console to not deplete the battery completely.
2018-06-01 19:08:21 +03:00
Kostas Missos
1521315450 Bug fixes, wording, etc 2018-06-01 19:02:13 +03:00
Kostas Missos
236ac03331 [Backup] Add dump verification 2018-06-01 18:48:59 +03:00
Kostas Missos
55d920bf00 [GFX] Fix hedump print last 1-16 bytes 2018-06-01 18:40:24 +03:00
38 changed files with 1257 additions and 852 deletions

View File

@@ -2,7 +2,9 @@ ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM") $(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif endif
include $(DEVKITARM)/base_rules CC = $(DEVKITARM)/bin/arm-none-eabi-gcc
LD = $(DEVKITARM)/bin/arm-none-eabi-ld
OBJCOPY = $(DEVKITARM)/bin/arm-none-eabi-objcopy
TARGET := ipl TARGET := ipl
BUILD := build_ipl BUILD := build_ipl
@@ -42,7 +44,7 @@ OBJS = $(addprefix $(BUILD)/, \
OBJS += $(addprefix $(BUILD)/, diskio.o ff.o ffunicode.o) OBJS += $(addprefix $(BUILD)/, diskio.o ff.o ffunicode.o)
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11# -Wall
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections
.PHONY: all clean .PHONY: all clean

View File

@@ -1,35 +0,0 @@
/*
* 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) 0x94000000 | ((((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

View File

@@ -18,7 +18,6 @@
#include "i2c.h" #include "i2c.h"
#include "gpio.h" #include "gpio.h"
#include "t210.h" #include "t210.h"
#include "util.h"
u32 btn_read() u32 btn_read()
{ {
@@ -37,38 +36,22 @@ u32 btn_wait()
u32 res = 0, btn = btn_read(); u32 res = 0, btn = btn_read();
int pwr = 0; int pwr = 0;
//Power button down, raise a filter. // Power button down, raise a filter.
if (btn & BTN_POWER) if (btn & BTN_POWER)
{ {
pwr = 1; pwr = 1;
btn &= ~BTN_POWER; btn &= 0xFFFFFFFE;
} }
do do
{ {
res = btn_read(); res = btn_read();
//Power button up, remove filter. // Power button up, remove filter.
if (!(res & BTN_POWER) && pwr) if (!(res & BTN_POWER) && pwr)
pwr = 0; pwr = 0;
else if (pwr) //Power button still down. // Power button still down.
res &= ~BTN_POWER; else if (pwr)
res &= 0xFFFFFFFE;
} while (btn == res); } while (btn == res);
return res;
}
u32 btn_wait_timeout(u32 time_ms)
{
u32 timeout = get_tmr() + (time_ms * 1000);
u32 res = btn_read();
u32 btn = res;
do
{
//Keep the new value until timeout is reached
if (btn == res)
res = btn_read();
} while (get_tmr() < timeout);
return res; return res;
} }

View File

@@ -25,6 +25,5 @@
u32 btn_read(); u32 btn_read();
u32 btn_wait(); u32 btn_wait();
u32 btn_wait_timeout(u32 time_ms);
#endif #endif

View File

@@ -51,14 +51,14 @@ static clock_t _clock_coresight = { 0xC, 0x18, 0x1D4, 9, 0, 4};
void clock_enable(const clock_t *clk) 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); CLOCK(clk->reset) = CLOCK(clk->reset) & ~(1 << clk->index) | (1 << clk->index);
//Disable. //Disable.
CLOCK(clk->enable) &= ~(1 << clk->index); CLOCK(clk->enable) &= ~(1 << clk->index);
//Configure clock source if required. //Configure clock source if required.
if (clk->source) if (clk->source)
CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29); CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29);
//Enable. //Enable.
CLOCK(clk->enable) = (CLOCK(clk->enable) & ~(1 << clk->index)) | (1 << clk->index); 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); CLOCK(clk->reset) &= ~(1 << clk->index);
} }
@@ -66,14 +66,14 @@ void clock_enable(const clock_t *clk)
void clock_disable(const clock_t *clk) 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); CLOCK(clk->reset) = CLOCK(clk->reset) & ~(1 << clk->index) | (1 << clk->index);
//Disable. //Disable.
CLOCK(clk->enable) &= ~(1 << clk->index); CLOCK(clk->enable) &= ~(1 << clk->index);
} }
void clock_enable_fuse(u32 enable) void clock_enable_fuse(u32 enable)
{ {
CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) = (CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) & 0xEFFFFFFF) | ((enable & 1) << 28); CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) = CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) & 0xEFFFFFFF | ((enable & 1) << 28) & 0x10000000;
} }
void clock_enable_uart(u32 idx) void clock_enable_uart(u32 idx)
@@ -144,9 +144,9 @@ void clock_disable_sor1()
void clock_enable_kfuse() void clock_enable_kfuse()
{ {
//clock_enable(&_clock_kfuse); //clock_enable(&_clock_kfuse);
CLOCK(0x8) = (CLOCK(0x8) & 0xFFFFFEFF) | 0x100; CLOCK(0x8) = CLOCK(0x8) & 0xFFFFFEFF | 0x100;
CLOCK(0x14) &= 0xFFFFFEFF; CLOCK(0x14) &= 0xFFFFFEFF;
CLOCK(0x14) = (CLOCK(0x14) & 0xFFFFFEFF) | 0x100; CLOCK(0x14) = CLOCK(0x14) & 0xFFFFFEFF | 0x100;
sleep(10); sleep(10);
CLOCK(0x8) &= 0xFFFFFEFF; CLOCK(0x8) &= 0xFFFFFEFF;
sleep(20); sleep(20);
@@ -259,7 +259,7 @@ static int _clock_sdmmc_is_enabled(u32 id)
return 0; return 0;
} }
static void _clock_sdmmc_set_enable(u32 id) static int _clock_sdmmc_set_enable(u32 id)
{ {
switch (id) switch (id)
{ {
@@ -274,7 +274,7 @@ static void _clock_sdmmc_set_enable(u32 id)
} }
} }
static void _clock_sdmmc_clear_enable(u32 id) static int _clock_sdmmc_clear_enable(u32 id)
{ {
switch (id) switch (id)
{ {

View File

@@ -77,15 +77,15 @@ void cluster_boot_cpu0(u32 entry)
sleep(2); sleep(2);
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02; CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02;
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02; 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_MISC) = CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF | 0x40000;
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02; CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02;
} }
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000)) while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000))
; ;
//Configure MSELECT source and enable clock. //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_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; 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. //Configure initial CPU clock frequency and enable clock.
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888;
@@ -95,7 +95,7 @@ void cluster_boot_cpu0(u32 entry)
clock_enable_coresight(); clock_enable_coresight();
//CAR2PMC_CPU_ACK_WIDTH should be set to 0. //CAR2PMC_CPU_ACK_WIDTH should be set to 0.
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000; CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) = CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) & 0xFFFFF000;
//Enable CPU rail. //Enable CPU rail.
_cluster_pmc_enable_partition(1, 0); _cluster_pmc_enable_partition(1, 0);

693
ipl/ctc_logo2.h Normal file
View File

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

View File

@@ -14,16 +14,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include "di.h" #include "di.h"
#include "t210.h" #include "t210.h"
#include "util.h" #include "util.h"
#include "i2c.h" #include "i2c.h"
#include "pmc.h" #include "pmc.h"
#include "max77620.h" #include "max77620.h"
#include "gpio.h"
#include "pinmux.h"
#include "di.inl" #include "di.inl"
@@ -58,25 +54,25 @@ void display_init()
PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000; PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000;
//Config pins. //Config pins.
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= 0xFFFFFFEF; PINMUX_AUX(0x1D0) &= 0xFFFFFFEF;
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= 0xFFFFFFEF; PINMUX_AUX(0x1D4) &= 0xFFFFFFEF;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= 0xFFFFFFEF; PINMUX_AUX(0x1FC) &= 0xFFFFFFEF;
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= 0xFFFFFFEF; PINMUX_AUX(0x200) &= 0xFFFFFFEF;
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= 0xFFFFFFEF; PINMUX_AUX(0x204) &= 0xFFFFFFEF;
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO); //Backlight +-5V. GPIO_3(0x00) = GPIO_3(0x00) & 0xFFFFFFFC | 0x3;
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE); //Backlight +-5V. GPIO_3(0x10) = GPIO_3(0x10) & 0xFFFFFFFC | 0x3;
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); //Backlight +5V enable. GPIO_3(0x20) = GPIO_3(0x20) & 0xFFFFFFFE | 0x1;
sleep(10000u);
GPIO_3(0x20) = GPIO_3(0x20) & 0xFFFFFFFD | 0x2;
sleep(10000); sleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); //Backlight -5V enable. GPIO_6(0x04) = GPIO_6(0x04) & 0xFFFFFFF8 | 0x7;
GPIO_6(0x14) = GPIO_6(0x14) & 0xFFFFFFF8 | 0x7;
sleep(10000); GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFD | 0x2;
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.
//Config display interface and display. //Config display interface and display.
MIPI_CAL(0x60) = 0; MIPI_CAL(0x60) = 0;
@@ -87,7 +83,7 @@ void display_init()
sleep(10000); sleep(10000);
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH); //Backlight Reset enable. GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFB | 0x4;
sleep(60000); sleep(60000);
@@ -135,18 +131,10 @@ void display_init()
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113); exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113);
} }
void display_backlight(u8 enable)
{
gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); //Backlight PWM.
}
void display_end() void display_end()
{ {
display_backlight(0); GPIO_6(0x24) &= 0xFFFFFFFE;
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1;
//TODO: figure out why this freezes.
/*DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1;
DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; DSI(_DSIREG(DSI_WR_DATA)) = 0x2805;
u32 end = HOST1X(0x30A4) + 5; u32 end = HOST1X(0x30A4) + 5;
@@ -169,17 +157,17 @@ void display_end()
sleep(50000); sleep(50000);
//gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable. GPIO_6(0x24) &= 0xFFFFFFFB;
//sleep(10000); sleep(10000);
//gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable. GPIO_3(0x20) &= 0xFFFFFFFD;
//sleep(10000); sleep(10000);
//gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable. GPIO_3(0x20) = (GPIO_3(0x20) >> 1) << 1;
//sleep(10000); sleep(10000);
//Disable clocks. //Disable clocks.
CLOCK(0x308) = 0x1010000; CLOCK(0x308) = 0x1010000;
@@ -188,12 +176,12 @@ void display_end()
CLOCK(0x324) = 0x18000000; CLOCK(0x324) = 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_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_6(0x04) &= 0xFFFFFFFE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFEF) | 0x10; PINMUX_AUX(0x1FC) = PINMUX_AUX(0x1FC) & 0xFFFFFFEF | 0x10;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; PINMUX_AUX(0x1FC) = (PINMUX_AUX(0x1FC) >> 2) << 2 | 1;
} }
void display_color_screen(u32 color) void display_color_screen(u32 color)
@@ -205,24 +193,21 @@ void display_color_screen(u32 color)
DISPLAY_A(_DIREG(DC_WIN_BD_WIN_OPTIONS)) = 0; DISPLAY_A(_DIREG(DC_WIN_BD_WIN_OPTIONS)) = 0;
DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0; DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0;
DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color; DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ; DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE | GENERAL_ACT_REQ;
sleep(35000); sleep(35000);
display_backlight(1); GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFE | 1;
} }
u32 *display_init_framebuffer(u32 *fb) u32 *display_init_framebuffer(u32 *fb)
{ {
//Sanitize framebuffer area. Aligned to 4MB.
memset((u32 *)0xC0000000, 0, 0x400000);
//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); exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer, 32);
sleep(35000); sleep(35000);
//Enable backlight GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFE | 1;
//display_backlight(1);
return (u32 *)0xC0000000; return (u32 *)0xC0000000;
} }

View File

@@ -341,9 +341,6 @@ void display_end();
/*! Show one single color on the display. */ /*! Show one single color on the display. */
void display_color_screen(u32 color); void display_color_screen(u32 color);
/*! Switches screen backlight ON/OFF. */
void display_backlight(u8 enable);
/*! Init display in full 1280x720 resolution (32bpp, line stride 768, framebuffer size = 1280*768*4 bytes). */ /*! Init display in full 1280x720 resolution (32bpp, line stride 768, framebuffer size = 1280*768*4 bytes). */
u32 *display_init_framebuffer(); u32 *display_init_framebuffer();

View File

@@ -50,7 +50,7 @@
/* This option switches f_expand function. (0:Disable or 1:Enable) */ /* This option switches f_expand function. (0:Disable or 1:Enable) */
#define FF_USE_CHMOD 1 #define FF_USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and f_utime(). /* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */

View File

@@ -15,7 +15,6 @@
*/ */
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
#include "gfx.h" #include "gfx.h"
static const u8 _gfx_font[] = { static const u8 _gfx_font[] = {
@@ -77,17 +76,18 @@ void gfx_init_ctxt(gfx_ctxt_t *ctxt, u32 *fb, u32 width, u32 height, u32 stride)
ctxt->stride = stride; ctxt->stride = stride;
} }
void gfx_clear_grey(gfx_ctxt_t *ctxt, u8 color) void gfx_clear(gfx_ctxt_t *ctxt, u32 color)
{
memset(ctxt->fb, color, 0x400000);
}
void gfx_clear_color(gfx_ctxt_t *ctxt, u32 color)
{ {
for (u32 i = 0; i < ctxt->height * ctxt->stride; i++) for (u32 i = 0; i < ctxt->height * ctxt->stride; i++)
ctxt->fb[i] = color; ctxt->fb[i] = color;
} }
void gfx_con_setfontsz(gfx_con_t *con, u8 font_size)
{
con->fntsz = font_size;
con->fontmult = font_size / 8;
}
void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt) void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt)
{ {
con->gfx_ctxt = ctxt; con->gfx_ctxt = ctxt;
@@ -96,6 +96,7 @@ void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt)
con->fgcol = 0xFFCCCCCC; con->fgcol = 0xFFCCCCCC;
con->fillbg = 0; con->fillbg = 0;
con->bgcol = 0xFF1B1B1B; con->bgcol = 0xFF1B1B1B;
gfx_con_setfontsz(con, 16);
} }
void gfx_con_setcol(gfx_con_t *con, u32 fgcol, int fillbg, u32 bgcol) void gfx_con_setcol(gfx_con_t *con, u32 fgcol, int fillbg, u32 bgcol)
@@ -123,27 +124,45 @@ void gfx_putc(gfx_con_t *con, char c)
{ {
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)]; u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
u32 *fb = con->gfx_ctxt->fb + con->x + con->y * con->gfx_ctxt->stride; u32 *fb = con->gfx_ctxt->fb + con->x + con->y * con->gfx_ctxt->stride;
for (u32 i = 0; i < 8; i++) for (u32 i = 0; i < con->fntsz; i+=con->fontmult)
{ {
u8 v = *cbuf++; u8 v = *cbuf++;
for (u32 j = 0; j < 8; j++) for (u32 k = 0; k < con->fontmult; k++)
{ {
if (v & 1) for (u32 j = 0; j < con->fntsz; j+=con->fontmult)
*fb = con->fgcol; {
else if (con->fillbg) if (v & 1)
*fb = con->bgcol; {
v >>= 1; *fb = con->fgcol;
fb++; for(u32 l = 0; l < con->fontmult - 1; l++)
{
fb++;
*fb = con->fgcol;
}
}
else if (con->fillbg)
{
*fb = con->bgcol;
for(u32 l = 0; l < con->fontmult - 1; l++)
{
fb++;
*fb = con->bgcol;
}
}
v >>= 1;
fb++;
}
fb += con->gfx_ctxt->stride - con->fntsz;
v = *cbuf;
} }
fb += con->gfx_ctxt->stride - 8;
} }
con->x += 8; con->x += con->fntsz;
} }
else if (c == '\n') else if (c == '\n')
{ {
con->x = 0; con->x = 0;
con->y += 8; con->y += con->fntsz;
if (con->y > con->gfx_ctxt->height - 8) if (con->y > con->gfx_ctxt->height - con->fntsz)
con->y = 0; con->y = 0;
} }
} }
@@ -188,6 +207,13 @@ static void _gfx_putn(gfx_con_t *con, u32 v, int base, char fill, int fcnt)
gfx_puts(con, p); gfx_puts(con, p);
} }
void gfx_putsep(gfx_con_t *con)
{
gfx_con_setfontsz(con, 8);
gfx_putc(con, '\n');
gfx_con_setfontsz(con, 16);
}
void gfx_printf(gfx_con_t *con, const char *fmt, ...) void gfx_printf(gfx_con_t *con, const char *fmt, ...)
{ {
va_list ap; va_list ap;
@@ -261,6 +287,8 @@ void gfx_printf(gfx_con_t *con, const char *fmt, ...)
void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len) void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len)
{ {
u8 prevFontSize = con->fntsz;
gfx_con_setfontsz(con, 8);
for(u32 i = 0; i < len; i++) for(u32 i = 0; i < len; i++)
{ {
if(i % 0x10 == 0) if(i % 0x10 == 0)
@@ -287,7 +315,7 @@ void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len)
u32 k = 0x10 - 1; u32 k = 0x10 - 1;
if (ln) if (ln)
{ {
k = (len & 0xF) - 1; k = len & 0xF - 1;
for (u32 j = 0; j < 0x10 - k; j++) for (u32 j = 0; j < 0x10 - k; j++)
gfx_puts(con, " "); gfx_puts(con, " ");
} }
@@ -304,6 +332,7 @@ void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len)
} }
} }
gfx_putc(con, '\n'); gfx_putc(con, '\n');
gfx_con_setfontsz(con, prevFontSize);
} }
static int abs(int x) static int abs(int x)
@@ -320,8 +349,8 @@ void gfx_set_pixel(gfx_ctxt_t *ctxt, u32 x, u32 y, u32 color)
void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 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 dx = abs(x1-x0), sx = x0 < x1 ? 1 : -1;
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1; int dy = abs(y1-y0), sy = y0 < y1 ? 1 : -1;
int err = (dx > dy ? dx : -dy) / 2, e2; int err = (dx > dy ? dx : -dy) / 2, e2;
while (1) while (1)
@@ -330,15 +359,20 @@ void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color)
if (x0 == x1 && y0 == y1) if (x0 == x1 && y0 == y1)
break; break;
e2 = err; e2 = err;
if (e2 >-dx) if (e2 >-dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
void gfx_set_logo(gfx_ctxt_t *ctxt, const u8 *buf)
{
u32 pos = 0;
for (u32 y = 1180; y < 1256; y++)
{
for (u32 x = 538; x < 696; x++)
{ {
err -= dy; ctxt->fb[x + y*ctxt->stride] = (0xFF << 24) | buf[pos] | (buf[pos + 1] << 8) | (buf[pos + 2] << 16);
x0 += sx; pos+=3;
}
if (e2 < dy)
{
err += dx;
y0 += sy;
} }
} }
} }

View File

@@ -35,15 +35,17 @@ typedef struct _gfx_con_t
u32 fgcol; u32 fgcol;
int fillbg; int fillbg;
u32 bgcol; u32 bgcol;
u32 fntsz;
u32 fontmult;
} gfx_con_t; } gfx_con_t;
void gfx_init_ctxt(gfx_ctxt_t *ctxt, u32 *fb, u32 width, u32 height, u32 stride); 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); void gfx_clear(gfx_ctxt_t *ctxt, u32 color);
void gfx_clear_color(gfx_ctxt_t *ctxt, u32 color);
void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt); void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt);
void gfx_con_setcol(gfx_con_t *con, u32 fgcol, int fillbg, u32 bgcol); void gfx_con_setcol(gfx_con_t *con, u32 fgcol, int fillbg, u32 bgcol);
void gfx_con_getpos(gfx_con_t *con, u32 *x, u32 *y); void gfx_con_getpos(gfx_con_t *con, u32 *x, u32 *y);
void gfx_con_setpos(gfx_con_t *con, u32 x, u32 y); void gfx_con_setpos(gfx_con_t *con, u32 x, u32 y);
void gfx_con_setfontsz(gfx_con_t *con, u8 font_size);
void gfx_putc(gfx_con_t *con, char c); void gfx_putc(gfx_con_t *con, char c);
void gfx_puts(gfx_con_t *con, const char *s); void gfx_puts(gfx_con_t *con, const char *s);
void gfx_printf(gfx_con_t *con, const char *fmt, ...); void gfx_printf(gfx_con_t *con, const char *fmt, ...);
@@ -51,5 +53,7 @@ void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len);
void gfx_set_pixel(gfx_ctxt_t *ctxt, u32 x, u32 y, u32 color); void gfx_set_pixel(gfx_ctxt_t *ctxt, u32 x, u32 y, u32 color);
void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color); void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color);
void gfx_putsep(gfx_con_t *con);
void gfx_set_logo(gfx_ctxt_t *ctxt, const u8 *buf);
#endif #endif

View File

@@ -90,5 +90,5 @@ void gpio_write(u32 port, u32 pins, int high)
int gpio_read(u32 port, u32 pins) int gpio_read(u32 port, u32 pins)
{ {
return (GPIO(_gpio_in[port]) & pins) ? 1 : 0; return GPIO(_gpio_in[port]) & pins ? 1 : 0;
} }

View File

@@ -97,7 +97,6 @@ static void _heap_free(heap_t *heap, u32 addr)
while (node) while (node)
{ {
if (!node->used) if (!node->used)
{
if (node->prev && !node->prev->used) if (node->prev && !node->prev->used)
{ {
node->prev->size += node->size + sizeof(hnode_t); node->prev->size += node->size + sizeof(hnode_t);
@@ -105,7 +104,6 @@ static void _heap_free(heap_t *heap, u32 addr)
if (node->next) if (node->next)
node->next->prev = node->prev; node->next->prev = node->prev;
} }
}
node = node->next; node = node->next;
} }
} }
@@ -131,6 +129,5 @@ void *calloc(u32 num, u32 size)
void free(void *buf) void free(void *buf)
{ {
if (buf != NULL) _heap_free(&_heap, (u32)buf);
_heap_free(&_heap, (u32)buf);
} }

372
ipl/hos.c
View File

@@ -31,7 +31,6 @@
#include "pkg1.h" #include "pkg1.h"
#include "pkg2.h" #include "pkg2.h"
#include "ff.h" #include "ff.h"
#include "di.h"
#include "gfx.h" #include "gfx.h"
extern gfx_ctxt_t gfx_ctxt; extern gfx_ctxt_t gfx_ctxt;
@@ -39,44 +38,17 @@ extern gfx_con_t gfx_con;
//#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__) //#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
typedef struct _launch_ctxt_t enum KB_FIRMWARE_VERSION {
{ KB_FIRMWARE_VERSION_100_200 = 0,
void *keyblob; KB_FIRMWARE_VERSION_300 = 1,
KB_FIRMWARE_VERSION_301 = 2,
KB_FIRMWARE_VERSION_400 = 3,
KB_FIRMWARE_VERSION_500 = 4,
KB_FIRMWARE_VERSION_MAX
};
void *pkg1; #define NUM_KEYBLOB_KEYS 5
const pkg1_id_t *pkg1_id; static const u8 keyblob_keyseeds[NUM_KEYBLOB_KEYS][0x10] = {
const pkg2_kernel_id_t *pkg2_kernel_id;
void *warmboot;
u32 warmboot_size;
void *secmon;
u32 secmon_size;
void *pkg2;
u32 pkg2_size;
void *kernel;
u32 kernel_size;
link_t kip1_list;
int svcperm;
int debugmode;
} launch_ctxt_t;
typedef struct _merge_kip_t
{
void *kip1;
link_t link;
} merge_kip_t;
#define KB_FIRMWARE_VERSION_100_200 0
#define KB_FIRMWARE_VERSION_300 1
#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
static const u8 keyblob_keyseeds[][0x10] = {
{ 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, //1.0.0 { 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, //1.0.0
{ 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, //3.0.0 { 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 { 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, //3.0.1
@@ -96,10 +68,10 @@ static const u8 console_keyseed[0x10] =
static const u8 key8_keyseed[] = static const u8 key8_keyseed[] =
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 }; { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
static const u8 master_keyseed_4xx_5xx[0x10] = static const u8 master_keyseed_4xx[0x10] =
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 }; { 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
static const u8 console_keyseed_4xx_5xx[0x10] = static const u8 console_keyseed_4xx[0x10] =
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 }; { 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
@@ -130,30 +102,28 @@ static void _se_lock()
gfx_hexdump(&gfx_con, SE_BASE, (void *)SE_BASE, 0x400);*/ gfx_hexdump(&gfx_con, SE_BASE, (void *)SE_BASE, 0x400);*/
} }
// <-- key derivation algorithm
int keygen(u8 *keyblob, u32 kb, void *tsec_fw) int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
{ {
u8 tmp[0x10]; u8 tmp[0x10];
if (kb > KB_FIRMWARE_VERSION_MAX) se_key_acc_ctrl(0x0D, 0x15);
return 0; se_key_acc_ctrl(0x0E, 0x15);
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) if (tsec_query(tmp, 1, tsec_fw) < 0)
return 0; return 0;
se_aes_key_set(13, tmp, 0x10); se_aes_key_set(0x0D, 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_crypt_block_ecb(0x0D, 0x00, tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp); se_aes_unwrap_key(0x0F, 0x0E, tmp);
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]); se_aes_crypt_block_ecb(0xD, 0x00, tmp, keyblob_keyseeds[kb]);
se_aes_unwrap_key(13, 14, tmp); se_aes_unwrap_key(0x0D, 0x0E, tmp);
//Clear SBK. // Clear SBK
se_aes_key_clear(14); se_aes_key_clear(0x0E);
//TODO: verify keyblob CMAC. //TODO: verify keyblob CMAC.
//se_aes_unwrap_key(11, 13, cmac_keyseed); //se_aes_unwrap_key(11, 13, cmac_keyseed);
@@ -161,46 +131,76 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
//if (!memcmp(keyblob, tmp, 0x10)) //if (!memcmp(keyblob, tmp, 0x10))
// return 0; // return 0;
se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed); se_aes_crypt_block_ecb(0x0D, 0, tmp, cmac_keyseed);
se_aes_unwrap_key(11, 13, cmac_keyseed); se_aes_unwrap_key(0x0B, 0x0D, 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_crypt_ctr(0x0D, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); //Package1 key. se_aes_key_set(0x0B, keyblob + 0x20 + 0x80, 0x10); // package1 key
se_aes_key_set(12, keyblob + 0x20, 0x10); se_aes_key_set(0x0C, keyblob + 0x20, 0x10);
se_aes_key_set(13, keyblob + 0x20, 0x10); se_aes_key_set(0x0D, keyblob + 0x20, 0x10);
se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail); se_aes_crypt_block_ecb(0x0C, 0, tmp, master_keyseed_retail);
switch (kb) switch (kb) {
{
case KB_FIRMWARE_VERSION_100_200: case KB_FIRMWARE_VERSION_100_200:
case KB_FIRMWARE_VERSION_300: case KB_FIRMWARE_VERSION_300:
case KB_FIRMWARE_VERSION_301: case KB_FIRMWARE_VERSION_301:
se_aes_unwrap_key(13, 15, console_keyseed); se_aes_unwrap_key(0x0D, 0x0F, console_keyseed);
se_aes_unwrap_key(12, 12, master_keyseed_retail); se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
break; break;
case KB_FIRMWARE_VERSION_400: case KB_FIRMWARE_VERSION_400:
se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx); se_aes_unwrap_key(0x0D, 0x0F, console_keyseed_4xx);
se_aes_unwrap_key(15, 15, console_keyseed); se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx); se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
se_aes_unwrap_key(12, 12, master_keyseed_retail); se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
break; break;
case KB_FIRMWARE_VERSION_500: case KB_FIRMWARE_VERSION_500:
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx); default:
se_aes_unwrap_key(15, 15, console_keyseed); se_aes_unwrap_key(0x0A, 0x0F, console_keyseed_4xx);
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx); se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
se_aes_unwrap_key(12, 12, master_keyseed_retail); se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
break; break;
} }
//Package2 key. // Package2 key
se_key_acc_ctrl(8, 0x15); se_key_acc_ctrl(0x08, 0x15);
se_aes_unwrap_key(8, 12, key8_keyseed); se_aes_unwrap_key(0x08, 0x0C, key8_keyseed);
return 1;
} }
typedef struct _launch_ctxt_t
{
void *keyblob;
void *pkg1;
const pkg1_id_t *pkg1_id;
void *warmboot;
u32 warmboot_size;
void *secmon;
u32 secmon_size;
void *pkg2;
u32 pkg2_size;
void *kernel;
u32 kernel_size;
link_t kip1_list;
u8 *svcperm;
u8 *debugmode;
} launch_ctxt_t;
typedef struct _merge_kip_t
{
void *kip1;
link_t link;
} merge_kip_t;
static int _read_emmc_pkg1(launch_ctxt_t *ctxt) static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
{ {
int res = 0; int res = 0;
@@ -216,10 +216,10 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1); ctxt->pkg1_id = pkg1_identify(ctxt->pkg1);
if (!ctxt->pkg1_id) if (!ctxt->pkg1_id)
{ {
gfx_printf(&gfx_con, "%kCould not identify package1 version (= '%s').%k\n", 0xFF0000FF, (char *)ctxt->pkg1 + 0x10, 0xFFFFFFFF); gfx_printf(&gfx_con, "%kCould not identify package1,\nVersion (= '%s').%k\n", 0xFF0000FF, (char *)ctxt->pkg1 + 0x10, 0xFFFFFFFF);
goto out; goto out;
} }
gfx_printf(&gfx_con, "Identified package1 ('%s'), Keyblob version %d\n\n", (char *)(ctxt->pkg1 + 0x10), ctxt->pkg1_id->kb); 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 *)malloc(NX_EMMC_BLOCKSIZE); ctxt->keyblob = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
@@ -326,22 +326,22 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
static int _config_svcperm(launch_ctxt_t *ctxt, const char *value) static int _config_svcperm(launch_ctxt_t *ctxt, const char *value)
{ {
if (*value == '1') if (*(u8 *)value == '1')
{ {
DPRINTF("Disabled SVC verification\n"); DPRINTF("Disabled SVC verification\n");
ctxt->svcperm = 1; ctxt->svcperm = malloc(1);
} }
return 1; return 1;
} }
static int _config_debugmode(launch_ctxt_t *ctxt, const char *value) static int _config_debugmode(launch_ctxt_t *ctxt, const char *value)
{ {
if (*value == '1') if (*(u8 *)value == '1')
{ {
DPRINTF("Enabled Debug mode\n"); DPRINTF("Enabled Debug mode\n");
ctxt->debugmode = 1; ctxt->debugmode = malloc(1);
} }
return 1;
} }
typedef struct _cfg_handler_t typedef struct _cfg_handler_t
@@ -372,21 +372,18 @@ static int _config(launch_ctxt_t *ctxt, ini_sec_t *cfg)
int hos_launch(ini_sec_t *cfg) int hos_launch(ini_sec_t *cfg)
{ {
int bootStateDramPkg2; int bootStatePackage2;
int bootStatePkg2Continue; int bootStateContinue;
int end_di = 0;
launch_ctxt_t ctxt; launch_ctxt_t ctxt;
memset(&ctxt, 0, sizeof(launch_ctxt_t)); memset(&ctxt, 0, sizeof(launch_ctxt_t));
list_init(&ctxt.kip1_list); list_init(&ctxt.kip1_list);
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
//Try to parse config if present.
if (cfg && !_config(&ctxt, cfg)) if (cfg && !_config(&ctxt, cfg))
return 0; return 0;
gfx_printf(&gfx_con, "Initializing...\n\n"); gfx_printf(&gfx_con, "Initializing...\n\n");
//Read package1 and the correct keyblob. //Read package1 and the correct keyblob.
@@ -394,131 +391,132 @@ int hos_launch(ini_sec_t *cfg)
return 0; return 0;
gfx_printf(&gfx_con, "Loaded package1 and keyblob\n"); gfx_printf(&gfx_con, "Loaded package1 and keyblob\n");
//Generate keys. //Generate keys.
keygen(ctxt.keyblob, ctxt.pkg1_id->kb, (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off); keygen(ctxt.keyblob, ctxt.pkg1_id->kb, (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off);
DPRINTF("Generated keys\n"); DPRINTF("Generated keys\n");
//Decrypt and unpack package1 if we require parts of it. //Decrypt and unpack package1 if we require parts of it.
if (!ctxt.warmboot || !ctxt.secmon) if (!ctxt.warmboot || !ctxt.secmon)
{ {
pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1); pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1);
pkg1_unpack((void *)ctxt.pkg1_id->warmboot_base, (void *)ctxt.pkg1_id->secmon_base, NULL, ctxt.pkg1_id, ctxt.pkg1); pkg1_unpack((void *)0x8000D000, (void *)ctxt.pkg1_id->secmon_base, ctxt.pkg1_id, ctxt.pkg1);
//gfx_hexdump(&gfx_con, 0x8000D000, (void *)0x8000D000, 0x100);
//gfx_hexdump(&gfx_con, ctxt.pkg1_id->secmon_base, (void *)ctxt.pkg1_id->secmon_base, 0x100);
gfx_printf(&gfx_con, "Decrypted and unpacked package1\n"); gfx_printf(&gfx_con, "Decrypted and unpacked package1\n");
} }
//Replace 'warmboot.bin' if requested. //Replace 'warmboot.bin' if requested.
if (ctxt.warmboot) if (ctxt.warmboot)
memcpy((void *)ctxt.pkg1_id->warmboot_base, ctxt.warmboot, ctxt.warmboot_size); memcpy((void *)0x8000D000, ctxt.warmboot, ctxt.warmboot_size);
//Set warmboot address in PMC if required. //Set warmboot address in PMC.
if (ctxt.pkg1_id->set_warmboot) PMC(APBDEV_PMC_SCRATCH1) = 0x8000D000;
PMC(APBDEV_PMC_SCRATCH1) = ctxt.pkg1_id->warmboot_base;
//Replace 'SecureMonitor' if requested. //Replace 'SecureMonitor' if requested.
if (ctxt.secmon) if (ctxt.secmon) {
memcpy((void *)ctxt.pkg1_id->secmon_base, ctxt.secmon, ctxt.secmon_size); memcpy((void *)ctxt.pkg1_id->secmon_base, ctxt.secmon, ctxt.secmon_size);
}
else else
{ {
//Else we patch it to allow for an unsigned package2 and patched kernel. //Else we patch it to allow for an unsigned package2.
patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset; patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset;
gfx_printf(&gfx_con, "%kPatching Security Monitor%k\n", 0xFF00BAFF, 0xFFCCCCCC); //In case a kernel patch option is set. Allows to disable Svc Verififcation or/and enable Debug mode
for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++) patch_t *kernel_patchset = ctxt.pkg1_id->kernel_patchset;
*(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val;
} if (secmon_patchset != NULL || (kernel_patchset != NULL && (ctxt.svcperm || ctxt.debugmode))) {
if (secmon_patchset != NULL)
gfx_printf(&gfx_con, "Loaded warmboot.bin and secmon\n");
//Read package2.
if (!_read_emmc_pkg2(&ctxt))
return 0;
gfx_printf(&gfx_con, "Read package2\n");
//Decrypt package2 and parse KIP1 blobs in INI1 section.
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2);
LIST_INIT(kip1_info);
pkg2_parse_kips(&kip1_info, pkg2_hdr);
gfx_printf(&gfx_con, "Parsed ini1\n");
//Use the kernel included in package2 in case we didn't load one already.
if (!ctxt.kernel)
{
ctxt.kernel = pkg2_hdr->data;
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
if (ctxt.svcperm || ctxt.debugmode)
{
u32 kernel_crc32 = crc32c(ctxt.kernel, ctxt.kernel_size);
ctxt.pkg2_kernel_id = pkg2_identify(kernel_crc32);
//In case a kernel patch option is set; allows to disable SVC verification or/and enable debug mode.
patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset;
if (kernel_patchset != NULL)
{ {
gfx_printf(&gfx_con, "%kPatching kernel%k\n", 0xFF00BAFF, 0xFFCCCCCC); gfx_printf(&gfx_con, "%kPatching Security Monitor%k\n", 0xFF00BAFF, 0xFFCCCCCC);
//TODO: this is a bit ugly, perhaps attach a 'key' to the patchset and pass it via ini. for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++)
if (ctxt.svcperm && kernel_patchset[0].off != 0xFFFFFFFF) *(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val;
*(vu32 *)(ctxt.kernel + kernel_patchset[0].off) = kernel_patchset[0].val;
if (ctxt.debugmode && kernel_patchset[1].off != 0xFFFFFFFF)
*(vu32 *)(ctxt.kernel + kernel_patchset[1].off) = kernel_patchset[1].val;
} }
gfx_printf(&gfx_con, "Loaded warmboot.bin and secmon\n");
//Read package2.
if (!_read_emmc_pkg2(&ctxt))
return 0;
gfx_printf(&gfx_con, "Read package2\n");
//Decrypt package2 and parse KIP1 blobs in INI1 section.
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2);
LIST_INIT(kip1_info);
pkg2_parse_kips(&kip1_info, pkg2_hdr);
gfx_printf(&gfx_con, "Parsed ini1\n");
//Use the kernel included in package2 in case we didn't load one already.
if (!ctxt.kernel)
{
ctxt.kernel = pkg2_hdr->data;
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
if (kernel_patchset != NULL && (ctxt.svcperm || ctxt.debugmode))
{
gfx_printf(&gfx_con, "%kPatching kernel%k\n", 0xFF00BAFF, 0xFFCCCCCC);
if (ctxt.svcperm && kernel_patchset[0].off != 0xFFFFFFFF)
*(vu32 *)(ctxt.kernel + kernel_patchset[0].off) = kernel_patchset[0].val;
if (ctxt.debugmode && kernel_patchset[1].off != 0xFFFFFFFF)
*(vu32 *)(ctxt.kernel + kernel_patchset[1].off) = kernel_patchset[1].val;
}
}
//Merge extra KIP1s into loaded ones.
gfx_printf(&gfx_con, "%kPatching kernel initial processes%k\n", 0xFF00BAFF, 0xFFCCCCCC);
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
//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");
} else {
//Read package2.
if (!_read_emmc_pkg2(&ctxt))
return 0;
gfx_printf(&gfx_con, "Loaded package2\n");
memcpy((void *)0xA9800000, ctxt.pkg2, ctxt.pkg2_size);
} }
} }
// Unmount SD Card
//Merge extra KIP1s into loaded ones.
gfx_printf(&gfx_con, "%kPatching kernel initial processes%k\n", 0xFF00BAFF, 0xFFCCCCCC);
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
//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");
//Unmount SD card.
f_mount(NULL, "", 1); f_mount(NULL, "", 1);
gfx_printf(&gfx_con, "\n%kBooting...%k\n", 0xFF00FF96, 0xFFCCCCCC); gfx_printf(&gfx_con, "\n%kBooting...%k\n", 0xFF00FF96, 0xFFCCCCCC);
se_aes_key_clear(8); se_aes_key_clear(0x8);
se_aes_key_clear(11); se_aes_key_clear(0xB);
switch (ctxt.pkg1_id->kb) switch (ctxt.pkg1_id->kb) {
{ case KB_FIRMWARE_VERSION_100_200:
case KB_FIRMWARE_VERSION_100_200: case KB_FIRMWARE_VERSION_300:
case KB_FIRMWARE_VERSION_300: case KB_FIRMWARE_VERSION_301:
case KB_FIRMWARE_VERSION_301: se_key_acc_ctrl(0xC, 0xFF);
se_key_acc_ctrl(12, 0xFF); se_key_acc_ctrl(0xD, 0xFF);
se_key_acc_ctrl(13, 0xFF); bootStatePackage2 = 2;
bootStateDramPkg2 = 2; bootStateContinue = 3;
bootStatePkg2Continue = 3; break;
end_di = 1; default:
break; case KB_FIRMWARE_VERSION_400:
default: case KB_FIRMWARE_VERSION_500:
case KB_FIRMWARE_VERSION_400: se_key_acc_ctrl(0xC, 0xFF);
case KB_FIRMWARE_VERSION_500: se_key_acc_ctrl(0xF, 0xFF);
se_key_acc_ctrl(12, 0xFF); bootStatePackage2 = 3;
se_key_acc_ctrl(15, 0xFF); bootStateContinue = 4;
bootStateDramPkg2 = 2; break;
bootStatePkg2Continue = 4;
break;
} }
//TODO: Don't Clear 'BootConfig' for retail >1.0.0. //Clear 'BootConfig' for retail systems.
memset((void *)0x4003D000, 0, 0x3000); memset((void *)0x4003D000, 0, 0x3000);
//pkg2_decrypt((void *)0xA9800000);
//sleep(10000);
//btn_wait();
//return 0;
//Lock SE before starting 'SecureMonitor'. //Lock SE before starting 'SecureMonitor'.
_se_lock(); _se_lock();
//< 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; vu32 *mb_in = (vu32 *)0x40002EF8;
//Non-zero: Secmon ready
vu32 *mb_out = (vu32 *)0x40002EFC; vu32 *mb_out = (vu32 *)0x40002EFC;
//Start from DRAM ready signal *mb_in = bootStatePackage2;
*mb_in = bootStateDramPkg2;
*mb_out = 0; *mb_out = 0;
//Wait for secmon to get ready. //Wait for secmon to get ready.
@@ -526,7 +524,10 @@ int hos_launch(ini_sec_t *cfg)
while (!*mb_out) while (!*mb_out)
sleep(1); sleep(1);
//TODO: pkg1.1 locks PMC scratches, we can do that too at some point. //Signal 'BootConfig'.
//*mb_in = 1;
//sleep(100);
/*PMC(0x4) = 0x7FFFF3; /*PMC(0x4) = 0x7FFFF3;
PMC(0x2C4) = 0xFFFFFFFF; PMC(0x2C4) = 0xFFFFFFFF;
PMC(0x2D8) = 0xFFAFFFFF; PMC(0x2D8) = 0xFFAFFFFF;
@@ -536,12 +537,11 @@ int hos_launch(ini_sec_t *cfg)
PMC(0x5BC) = 0xFFFFFFFF; PMC(0x5BC) = 0xFFFFFFFF;
PMC(0x5C0) = 0xFFAAFFFF;*/ PMC(0x5C0) = 0xFFAAFFFF;*/
//Disable display. //TODO: Cleanup.
if (end_di) //display_end();
display_end();
//Signal to pkg2 ready and continue boot. //Signal to continue boot.
*mb_in = bootStatePkg2Continue; *mb_in = bootStateContinue;
//Halt ourselves in waitevent state. //Halt ourselves in waitevent state.
while (1) while (1)

View File

@@ -46,7 +46,7 @@ static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size)
base[0] = (2 * size - 2) | 0x2800; //Set size and send mode. base[0] = (2 * size - 2) | 0x2800; //Set size and send mode.
_i2c_wait(base); //Kick transaction. _i2c_wait(base); //Kick transaction.
base[0] = (base[0] & 0xFFFFFDFF) | 0x200; base[0] = base[0] & 0xFFFFFDFF | 0x200;
while (base[7] & 0x100) while (base[7] & 0x100)
; ;
@@ -66,7 +66,7 @@ static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x)
base[0] = (2 * size - 2) | 0x2840; //Set size and recv mode. base[0] = (2 * size - 2) | 0x2840; //Set size and recv mode.
_i2c_wait(base); //Kick transaction. _i2c_wait(base); //Kick transaction.
base[0] = (base[0] & 0xFFFFFDFF) | 0x200; base[0] = base[0] & 0xFFFFFDFF | 0x200;
while (base[7] & 0x100) while (base[7] & 0x100)
; ;
@@ -94,11 +94,11 @@ void i2c_init(u32 idx)
break; break;
} }
(vu32)base[0x22]; vu32 dummy = base[0x22];
base[0x1A] = base[0x1A]; base[0x1A] = base[0x1A];
} }
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size) u32 i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size)
{ {
u8 tmp[4]; u8 tmp[4];
@@ -108,7 +108,7 @@ int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size)
tmp[0] = y; tmp[0] = y;
memcpy(tmp + 1, buf, size); memcpy(tmp + 1, buf, size);
return _i2c_send_pkt(idx, x, tmp, size + 1); _i2c_send_pkt(idx, x, tmp, size + 1);
} }
int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y) int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y)
@@ -119,9 +119,9 @@ int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y)
return res; return res;
} }
int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b) u32 i2c_send_byte(u32 idx, u32 x, u32 y, u8 b)
{ {
return i2c_send_buf_small(idx, x, y, &b, 1); i2c_send_buf_small(idx, x, y, &b, 1);
} }
u8 i2c_recv_byte(u32 idx, u32 x, u32 y) u8 i2c_recv_byte(u32 idx, u32 x, u32 y)

View File

@@ -27,9 +27,9 @@
#define I2C_6 5 #define I2C_6 5
void i2c_init(u32 idx); void i2c_init(u32 idx);
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size); u32 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_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); u32 i2c_send_byte(u32 idx, u32 x, u32 y, u8 b);
u8 i2c_recv_byte(u32 idx, u32 x, u32 y); u8 i2c_recv_byte(u32 idx, u32 x, u32 y);
#endif #endif

View File

@@ -91,51 +91,3 @@ int ini_parse(link_t *dst, char *ini_path)
return 1; return 1;
} }
void ini_free(link_t *dst)
{
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, dst, link)
{
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);
}
}
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);
}

View File

@@ -35,8 +35,5 @@ typedef struct _ini_sec_t
} ini_sec_t; } ini_sec_t;
int ini_parse(link_t *dst, char *ini_path); int ini_parse(link_t *dst, char *ini_path);
void ini_free(link_t *dst);
ini_sec_t *ini_clone_section(ini_sec_t *cfg);
void ini_free_section(ini_sec_t *cfg);
#endif #endif

View File

@@ -38,6 +38,7 @@
#include "gpio.h" #include "gpio.h"
#include "sdmmc.h" #include "sdmmc.h"
#include "ff.h" #include "ff.h"
#include "ctc_logo2.h"
#include "tui.h" #include "tui.h"
#include "heap.h" #include "heap.h"
#include "list.h" #include "list.h"
@@ -47,6 +48,7 @@
#include "hos.h" #include "hos.h"
#include "pkg1.h" #include "pkg1.h"
#include "mmc.h" #include "mmc.h"
#include "lz.h"
//TODO: ugly. //TODO: ugly.
gfx_ctxt_t gfx_ctxt; gfx_ctxt_t gfx_ctxt;
@@ -61,6 +63,7 @@ sdmmc_t sd_sdmmc;
sdmmc_storage_t sd_storage; sdmmc_storage_t sd_storage;
FATFS sd_fs; FATFS sd_fs;
int sd_mounted; int sd_mounted;
u8 *Kc_HEKATE_LOGO;
int sd_mount() int sd_mount()
{ {
@@ -93,9 +96,9 @@ void sd_unmount()
{ {
if (sd_mounted) if (sd_mounted)
{ {
gfx_puts(&gfx_con, "Unmounting SD card...\n");
f_mount(NULL, "", 1); f_mount(NULL, "", 1);
sdmmc_storage_end(&sd_storage); sdmmc_storage_end(&sd_storage);
sd_mounted = 0;
} }
} }
@@ -156,17 +159,17 @@ void panic(u32 val)
void config_oscillators() void config_oscillators()
{ {
CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3 | 4;
SYSCTR0(SYSCTR0_CNTFID0) = 19200000; SYSCTR0(SYSCTR0_CNTFID0) = 19200000;
TMR(0x14) = 0x45F; TMR(0x14) = 0x45F;
CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071; CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071;
PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81) | 0xE; PMC(APBDEV_PMC_OSC_EDPD_OVER) = PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81 | 0xE;
PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF) | 0x400000; PMC(APBDEV_PMC_OSC_EDPD_OVER) = PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF | 0x400000;
PMC(APBDEV_PMC_CNTRL2) = (PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF) | 0x1000; PMC(APBDEV_PMC_CNTRL2) = PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF | 0x1000;
PMC(APBDEV_PMC_SCRATCH188) = (PMC(APBDEV_PMC_SCRATCH188) & 0xFCFFFFFF) | 0x2000000; PMC(APBDEV_PMC_SCRATCH188) = PMC(APBDEV_PMC_SCRATCH188) & 0xFCFFFFFF | 0x2000000;
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10; CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10;
CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF; CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF;
PMC(APBDEV_PMC_TSC_MULT) = (PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000) | 0x249F; //0x249F = 19200000 * (16 / 32.768 kHz) PMC(APBDEV_PMC_TSC_MULT) = PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000 | 0x249F; //0x249F = 19200000 * (16 / 32.768 kHz)
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444;
CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000;
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2;
@@ -247,9 +250,9 @@ void mbist_workaround()
CLOCK(0x554) = 0; CLOCK(0x554) = 0;
CLOCK(0xD0) &= 0x1F7FFFFF; CLOCK(0xD0) &= 0x1F7FFFFF;
CLOCK(0x410) &= 0xFFFF3FFF; CLOCK(0x410) &= 0xFFFF3FFF;
CLOCK(0x148) = (CLOCK(0x148) & 0x1FFFFFFF) | 0x80000000; CLOCK(0x148) = CLOCK(0x148) & 0x1FFFFFFF | 0x80000000;
CLOCK(0x180) = (CLOCK(0x180) & 0x1FFFFFFF) | 0x80000000; CLOCK(0x180) = CLOCK(0x180) & 0x1FFFFFFF | 0x80000000;
CLOCK(0x6A0) = (CLOCK(0x6A0) & 0x1FFFFFFF) | 0x80000000; CLOCK(0x6A0) = CLOCK(0x6A0) & 0x1FFFFFFF | 0x80000000;
} }
void config_se_brom() void config_se_brom()
@@ -268,6 +271,7 @@ void config_se_brom()
// Clear the boot reason to avoid problems later // Clear the boot reason to avoid problems later
PMC(APBDEV_PMC_SCRATCH200) = 0x0; PMC(APBDEV_PMC_SCRATCH200) = 0x0;
PMC(APBDEV_PMC_RST_STATUS_0) = 0x0; PMC(APBDEV_PMC_RST_STATUS_0) = 0x0;
PMC(APBDEV_PMC_SCRATCH49_0) = 0x0;
} }
void config_hw() void config_hw()
@@ -324,7 +328,7 @@ void config_hw()
config_pmc_scratch(); config_pmc_scratch();
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = (CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888) | 0x3333; CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888 | 0x3333;
mc_config_carveout(); mc_config_carveout();
@@ -335,7 +339,7 @@ void config_hw()
void print_fuseinfo() void print_fuseinfo()
{ {
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
gfx_printf(&gfx_con, "%k(Unlocked) fuse cache:\n\n%k", 0xFFFFDD00, 0xFFCCCCCC); gfx_printf(&gfx_con, "%k(Unlocked) fuse cache:\n\n%k", 0xFFFFDD00, 0xFFCCCCCC);
@@ -364,7 +368,7 @@ void print_fuseinfo()
void print_kfuseinfo() void print_kfuseinfo()
{ {
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
gfx_printf(&gfx_con, "%kKFuse contents:\n\n%k", 0xFFFFDD00, 0xFFCCCCCC); gfx_printf(&gfx_con, "%kKFuse contents:\n\n%k", 0xFFFFDD00, 0xFFCCCCCC);
@@ -397,7 +401,7 @@ void print_kfuseinfo()
void print_mmc_info() void print_mmc_info()
{ {
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
static const u32 SECTORS_TO_MIB_COEFF = 11; static const u32 SECTORS_TO_MIB_COEFF = 11;
@@ -502,21 +506,29 @@ void print_mmc_info()
Cmd Classes: %02X\n\ Cmd Classes: %02X\n\
Capacity: %s\n\ Capacity: %s\n\
Max Speed: %d MB/s (%d MHz)\n\ Max Speed: %d MB/s (%d MHz)\n\
Type Support: %s\n\n", Type Support: ",
storage.csd.mmca_vsn, storage.ext_csd.rev, storage.ext_csd.dev_version, storage.csd.cmdclass, storage.csd.mmca_vsn, storage.ext_csd.rev, storage.ext_csd.dev_version, storage.csd.cmdclass,
storage.csd.capacity == (4096 * 512) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF, card_type_support); storage.csd.capacity == (4096 * 512) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF);
gfx_con_setfontsz(&gfx_con, 8);
gfx_printf(&gfx_con, "%s", card_type_support);
gfx_con_setfontsz(&gfx_con, 16);
gfx_printf(&gfx_con, "\n\n", card_type_support);
u32 boot_size = storage.ext_csd.boot_mult << 17; u32 boot_size = storage.ext_csd.boot_mult << 17;
u32 rpmb_size = storage.ext_csd.rpmb_mult << 17; u32 rpmb_size = storage.ext_csd.rpmb_mult << 17;
gfx_printf(&gfx_con, "%keMMC Partitions:%k\n", 0xFFFFDD00, 0xFFCCCCCC); gfx_printf(&gfx_con, "%keMMC Partitions:%k\n", 0xFFFFDD00, 0xFFCCCCCC);
gfx_printf(&gfx_con, " 1: %kBOOT0 %kSize: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF00FF96, 0xFFCCCCCC, gfx_printf(&gfx_con, " 1: %kBOOT0 %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF00FF96, 0xFFCCCCCC,
boot_size / 1024, boot_size / 1024 / 512); boot_size / 1024, boot_size / 1024 / 512);
gfx_printf(&gfx_con, " 2: %kBOOT1 %kSize: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF00FF96, 0xFFCCCCCC, gfx_putsep(&gfx_con);
gfx_printf(&gfx_con, " 2: %kBOOT1 %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF00FF96, 0xFFCCCCCC,
boot_size / 1024, boot_size / 1024 / 512); boot_size / 1024, boot_size / 1024 / 512);
gfx_printf(&gfx_con, " 3: %kRPMB %kSize: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF00FF96, 0xFFCCCCCC, gfx_putsep(&gfx_con);
gfx_printf(&gfx_con, " 3: %kRPMB %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF00FF96, 0xFFCCCCCC,
rpmb_size / 1024, rpmb_size / 1024 / 512); rpmb_size / 1024, rpmb_size / 1024 / 512);
gfx_printf(&gfx_con, " 0: %kGPP (USER) %kSize: %5d MiB (LBA Sectors: 0x%07X)\n\n", 0xFF00FF96, 0xFFCCCCCC, gfx_putsep(&gfx_con);
gfx_printf(&gfx_con, " 0: %kGPP (USER) %k\n Size: %5d MiB (LBA Sectors: 0x%07X)\n\n", 0xFF00FF96, 0xFFCCCCCC,
storage.sec_cnt >> SECTORS_TO_MIB_COEFF, storage.sec_cnt); storage.sec_cnt >> SECTORS_TO_MIB_COEFF, storage.sec_cnt);
gfx_putsep(&gfx_con);
gfx_printf(&gfx_con, "%kGPP (eMMC USER) partition table:%k\n", 0xFFFFDD00, 0xFFCCCCCC); gfx_printf(&gfx_con, "%kGPP (eMMC USER) partition table:%k\n", 0xFFFFDD00, 0xFFCCCCCC);
sdmmc_storage_set_mmc_partition(&storage, 0); sdmmc_storage_set_mmc_partition(&storage, 0);
@@ -525,9 +537,10 @@ void print_mmc_info()
int gpp_idx = 0; int gpp_idx = 0;
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link) LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
{ {
gfx_printf(&gfx_con, " %02d: %k%s%k\n Size: % 5d MiB (LBA Sectors 0x%07X, LBA Range: %08X-%08X)\n", gfx_printf(&gfx_con, " %02d: %k%s%k\n Size: % 5d MiB (LBA Sectors 0x%07X)\n LBA Range: %08X-%08X\n",
gpp_idx++, 0xFF14FDAE, part->name, 0xFFCCCCCC, (part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF, gpp_idx++, 0xFF14FDAE, part->name, 0xFFCCCCCC, (part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
part->lba_end - part->lba_start + 1, part->lba_start, part->lba_end); part->lba_end - part->lba_start + 1, part->lba_start, part->lba_end);
gfx_putsep(&gfx_con);
} }
} }
} }
@@ -540,7 +553,7 @@ out:
void print_sdcard_info() void print_sdcard_info()
{ {
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
static const u32 SECTORS_TO_MIB_COEFF = 11; static const u32 SECTORS_TO_MIB_COEFF = 11;
@@ -591,7 +604,7 @@ void print_sdcard_info()
void print_tsec_key() void print_tsec_key()
{ {
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
sdmmc_storage_t storage; sdmmc_storage_t storage;
@@ -606,6 +619,7 @@ void print_tsec_key()
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1); const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
if (!pkg1_id) if (!pkg1_id)
{ {
gfx_con_setfontsz(&gfx_con, 8);
EPRINTFARGS("Could not identify package1 version to read TSEC firmware (= '%s').", EPRINTFARGS("Could not identify package1 version to read TSEC firmware (= '%s').",
(char *)pkg1 + 0x10); (char *)pkg1 + 0x10);
goto out; goto out;
@@ -638,12 +652,14 @@ out:;
void reboot_normal() void reboot_normal()
{ {
sd_unmount(); sd_unmount();
free(Kc_HEKATE_LOGO);
panic(0x21); //Bypass fuse programming in package1. panic(0x21); //Bypass fuse programming in package1.
} }
void reboot_rcm() void reboot_rcm()
{ {
sd_unmount(); sd_unmount();
free(Kc_HEKATE_LOGO);
PMC(APBDEV_PMC_SCRATCH0) = 2; //Reboot into rcm. PMC(APBDEV_PMC_SCRATCH0) = 2; //Reboot into rcm.
PMC(0) |= 0x10; PMC(0) |= 0x10;
while (1) while (1)
@@ -653,6 +669,7 @@ void reboot_rcm()
void power_off() void power_off()
{ {
sd_unmount(); sd_unmount();
free(Kc_HEKATE_LOGO);
//TODO: we should probably make sure all regulators are powered off properly. //TODO: we should probably make sure all regulators are powered off properly.
i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF); i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
} }
@@ -679,6 +696,7 @@ int dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char* outFilename,
if(!sdmmc_storage_read(storage, lbaCurrVer, num, bufEm)) if(!sdmmc_storage_read(storage, lbaCurrVer, num, bufEm))
{ {
gfx_con_setfontsz(&gfx_con, 16);
EPRINTFARGS("\nFailed to read %d blocks @ LBA %08X\nfrom eMMC. Aborting..\n", EPRINTFARGS("\nFailed to read %d blocks @ LBA %08X\nfrom eMMC. Aborting..\n",
num, lbaCurrVer); num, lbaCurrVer);
@@ -689,6 +707,7 @@ int dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char* outFilename,
} }
if (!(f_read(&fp, bufSd, num, NULL) == FR_OK)) if (!(f_read(&fp, bufSd, num, NULL) == FR_OK))
{ {
gfx_con_setfontsz(&gfx_con, 16);
EPRINTFARGS("\nFailed to read %d blocks from sd card.\nVerification failed..\n", num); EPRINTFARGS("\nFailed to read %d blocks from sd card.\nVerification failed..\n", num);
free(bufEm); free(bufEm);
@@ -699,6 +718,7 @@ int dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char* outFilename,
if(!memcmp(bufEm, bufSd, num << 9)) if(!memcmp(bufEm, bufSd, num << 9))
{ {
gfx_con_setfontsz(&gfx_con, 16);
EPRINTFARGS("\nVerification failed.\nVerification failed..\n", num); EPRINTFARGS("\nVerification failed.\nVerification failed..\n", num);
free(bufEm); free(bufEm);
@@ -727,6 +747,7 @@ int dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char* outFilename,
} }
else else
{ {
gfx_con_setfontsz(&gfx_con, 16);
EPRINTF("\nFile not found or could not be loaded.\nVerification failed..\n"); EPRINTF("\nFile not found or could not be loaded.\nVerification failed..\n");
return 1; return 1;
} }
@@ -753,7 +774,8 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
memcpy(partialIdxFilename, "partial.idx", 11); memcpy(partialIdxFilename, "partial.idx", 11);
partialIdxFilename[11] = 0; partialIdxFilename[11] = 0;
gfx_printf(&gfx_con, "\nSD Card free space: %d MiB, Total backup size %d MiB\n\n", gfx_con_setfontsz(&gfx_con, 8);
gfx_printf(&gfx_con, "\nSD Card free space: %d MiB, Total dump size %d MiB\n\n",
sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF, sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF,
totalSectors >> SECTORS_TO_MIB_COEFF); totalSectors >> SECTORS_TO_MIB_COEFF);
@@ -768,19 +790,20 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
{ {
isSmallSdCard = 1; isSmallSdCard = 1;
gfx_printf(&gfx_con, "%k\nSD card free space is smaller than total backup size.%k\n", 0xFF00BAFF, 0xFFCCCCCC); gfx_printf(&gfx_con, "%k\nSD card free space is smaller than dump total size.%k\n", 0xFF00BAFF, 0xFFCCCCCC);
if (!maxSplitParts) if (!maxSplitParts)
{ {
EPRINTF("Not enough free space for Partial Backup."); gfx_con_setfontsz(&gfx_con, 16);
EPRINTF("Not enough free space for partial dumping.");
return 0; return 0;
} }
} }
// Check if we continuing a previous raw eMMC backup in progress. // Check if we continuing a previous raw eMMC dump in progress.
if (f_open(&partialIdxFp, partialIdxFilename, FA_READ) == FR_OK) if (f_open(&partialIdxFp, partialIdxFilename, FA_READ) == FR_OK)
{ {
gfx_printf(&gfx_con, "%kFound Partial Backup in progress. Continuing...%k\n\n", 0xFF14FDAE, 0xFFCCCCCC); gfx_printf(&gfx_con, "%kFound partial dump in progress. Continuing...%k\n\n", 0xFF14FDAE, 0xFFCCCCCC);
partialDumpInProgress = 1; partialDumpInProgress = 1;
// Force partial dumping, even if the card is larger. // Force partial dumping, even if the card is larger.
@@ -791,18 +814,19 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
if (!maxSplitParts) if (!maxSplitParts)
{ {
EPRINTF("Not enough free space for Partial Backup."); gfx_con_setfontsz(&gfx_con, 16);
EPRINTF("Not enough free space for partial dumping.");
return 0; return 0;
} }
// Increase maxSplitParts to accommodate previously backed up parts // Increase maxSplitParts to accommodate previously dumped parts
maxSplitParts += currPartIdx; maxSplitParts += currPartIdx;
} }
else if (isSmallSdCard) else if (isSmallSdCard)
gfx_printf(&gfx_con, "%kPartial Backup enabled (with %d MiB parts)...%k\n\n", 0xFF00BAFF, multipartSplitSize >> 20, 0xFFCCCCCC); gfx_printf(&gfx_con, "%kPartial dumping enabled (with %d MiB parts)...%k\n\n", 0xFF00BAFF, multipartSplitSize >> 20, 0xFFCCCCCC);
// Check if filesystem is FAT32 or the free space is smaller and backup in parts // Check if filesystem is FAT32 or the free space is smaller and dump in parts
if (((sd_fs.fs_type != FS_EXFAT) && totalSectors > (FAT32_FILESIZE_LIMIT / NX_EMMC_BLOCKSIZE)) | isSmallSdCard) if (((sd_fs.fs_type != FS_EXFAT) && totalSectors > (FAT32_FILESIZE_LIMIT / NX_EMMC_BLOCKSIZE)) | isSmallSdCard)
{ {
u32 multipartSplitSectors = multipartSplitSize / NX_EMMC_BLOCKSIZE; u32 multipartSplitSectors = multipartSplitSize / NX_EMMC_BLOCKSIZE;
@@ -823,7 +847,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
else else
outFilename[sdPathLen + 1] = 0; outFilename[sdPathLen + 1] = 0;
} }
// Continue from where we left, if Partial Backup in progress. // Continue from where we left, if partial dump in progress.
else else
{ {
if (numSplitParts >= 10 && currPartIdx < 10) if (numSplitParts >= 10 && currPartIdx < 10)
@@ -839,6 +863,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
FIL fp; FIL fp;
if (f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) if (f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
{ {
gfx_con_setfontsz(&gfx_con, 16);
EPRINTFARGS("Error creating file %s.\n", outFilename); EPRINTFARGS("Error creating file %s.\n", outFilename);
return 0; return 0;
@@ -852,7 +877,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
u32 prevPct = 200; u32 prevPct = 200;
int retryCount = 0; int retryCount = 0;
// Continue from where we left, if Partial Backup in progress. // Continue from where we left, if partial dump in progress.
if (partialDumpInProgress) if (partialDumpInProgress)
{ {
lba_curr += currPartIdx * (multipartSplitSize / NX_EMMC_BLOCKSIZE); lba_curr += currPartIdx * (multipartSplitSize / NX_EMMC_BLOCKSIZE);
@@ -870,7 +895,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
// Verify part // Verify part
if (dump_emmc_verify(storage, lba_curr, outFilename, NUM_SECTORS_PER_ITER, part)) if (dump_emmc_verify(storage, lba_curr, outFilename, NUM_SECTORS_PER_ITER, part))
{ {
EPRINTF("\nPress any key and try again...\n"); EPRINTF("\nPress any key and try again.\n");
free(buf); free(buf);
return 0; return 0;
@@ -887,7 +912,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
// Always create partial.idx before next part, in case a fatal error occurs. // Always create partial.idx before next part, in case a fatal error occurs.
if (isSmallSdCard) if (isSmallSdCard)
{ {
// Create partial backup index file // Create partial dump index file
if (f_open(&partialIdxFp, partialIdxFilename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) if (f_open(&partialIdxFp, partialIdxFilename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
{ {
f_write(&partialIdxFp, &currPartIdx, 4, NULL); f_write(&partialIdxFp, &currPartIdx, 4, NULL);
@@ -895,20 +920,22 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
} }
else else
{ {
gfx_con_setfontsz(&gfx_con, 16);
EPRINTF("\nError creating partial.idx file.\n"); EPRINTF("\nError creating partial.idx file.\n");
free(buf); free(buf);
return 0; return 0;
} }
// More parts to backup that do not currently fit the sd card free space or fatal error // More parts to dump that do not currently fit the sd card free space or fatal error
if (currPartIdx >= maxSplitParts) if (currPartIdx >= maxSplitParts)
{ {
gfx_puts(&gfx_con, "\n\n1. Press any key and Power off Switch from the main menu.\n\ gfx_puts(&gfx_con, "\n\n1. Press any key and Power off Switch from the main menu.\n\
2. Move the files from SD card to free space.\n\ 2. Move the files from SD card to free space.\n\
Don\'t move the partial.idx file!\n\ Don\'t move the partial.idx file!\n\
3. Unplug and re-plug USB while pressing Vol+.\n\ 3. Unplug and re-plug USB while pressing Vol+.\n\
4. Run hekate again and press Backup eMMC RAW GPP (or eMMC USER) to continue.\n"); 4. Run hekate - ipl again and press Dump RAW eMMC or eMMC USER to continue\n");
gfx_con_setfontsz(&gfx_con, 16);
free(buf); free(buf);
return 1; return 1;
@@ -918,6 +945,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
// Create next part // Create next part
if (f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) if (f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
{ {
gfx_con_setfontsz(&gfx_con, 16);
EPRINTFARGS("Error creating file %s.\n", outFilename); EPRINTFARGS("Error creating file %s.\n", outFilename);
free(buf); free(buf);
@@ -936,9 +964,10 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
sleep(150000); sleep(150000);
if (retryCount >= 3) if (retryCount >= 3)
{ {
EPRINTFARGS("\nFailed to read %d blocks @ LBA %08X from eMMC. Aborting..\n", gfx_con_setfontsz(&gfx_con, 16);
EPRINTFARGS("\nFailed to read %d blocks @ LBA %08X\nfrom eMMC. Aborting..\n",
num, lba_curr); num, lba_curr);
EPRINTF("\nPress any key and try again...\n"); EPRINTF("\nPress any key and try again.\n");
free(buf); free(buf);
f_close(&fp); f_close(&fp);
@@ -948,8 +977,9 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
res = f_write(&fp, buf, NX_EMMC_BLOCKSIZE * num, NULL); res = f_write(&fp, buf, NX_EMMC_BLOCKSIZE * num, NULL);
if (res) if (res)
{ {
gfx_con_setfontsz(&gfx_con, 16);
EPRINTFARGS("\nFatal error (%d) when writing to SD Card", res); EPRINTFARGS("\nFatal error (%d) when writing to SD Card", res);
EPRINTF("\nPress any key and try again...\n"); EPRINTF("\nPress any key and try again.\n");
free(buf); free(buf);
f_close(&fp); f_close(&fp);
@@ -975,14 +1005,14 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
} }
tui_pbar(&gfx_con, 0, gfx_con.y, 100, 0xFFCCCCCC, 0xFF555555); tui_pbar(&gfx_con, 0, gfx_con.y, 100, 0xFFCCCCCC, 0xFF555555);
// Backup operation ended successfully // Dumping process ended successfully
free(buf); free(buf);
f_close(&fp); f_close(&fp);
// Verify last part or single file backup // Verify last part or single file dump
if (dump_emmc_verify(storage, lba_curr, outFilename, NUM_SECTORS_PER_ITER, part)) if (dump_emmc_verify(storage, lba_curr, outFilename, NUM_SECTORS_PER_ITER, part))
{ {
EPRINTF("\nPress any key and try again...\n"); EPRINTF("\nPress any key and try again.\n");
free(buf); free(buf);
return 0; return 0;
@@ -990,11 +1020,12 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
else else
tui_pbar(&gfx_con, 0, gfx_con.y, 100, 0xFF00FF96, 0xFF005515); tui_pbar(&gfx_con, 0, gfx_con.y, 100, 0xFF00FF96, 0xFF005515);
// Remove partial backup index file if no fatal errors occurred. gfx_con_setfontsz(&gfx_con, 16);
// Remove partial dump index file if no fatal errors occurred.
if(isSmallSdCard) if(isSmallSdCard)
{ {
f_unlink(partialIdxFilename); f_unlink(partialIdxFilename);
gfx_printf(&gfx_con, "%k\n\nYou can now join the files\nand get the complete eMMC RAW GPP backup.", 0xFFCCCCCC); gfx_printf(&gfx_con, "%k\n\nYou can now join the files\nand get the complete raw eMMC dump.", 0xFFCCCCCC);
} }
gfx_puts(&gfx_con, "\n\n"); gfx_puts(&gfx_con, "\n\n");
@@ -1013,14 +1044,14 @@ static void dump_emmc_selected(dumpType_t dumpType)
{ {
int res = 0; int res = 0;
u32 timer = 0; u32 timer = 0;
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
if (!sd_mount()) if (!sd_mount())
goto out; goto out;
gfx_puts(&gfx_con, "Checking for available free space...\n\n"); gfx_puts(&gfx_con, "Checking for available free space...\n\n");
// Get SD Card free space for Partial Backup // Get SD Card free space for partial dumping
f_getfree("", &sd_fs.free_clst, NULL); f_getfree("", &sd_fs.free_clst, NULL);
sdmmc_storage_t storage; sdmmc_storage_t storage;
@@ -1047,7 +1078,7 @@ static void dump_emmc_selected(dumpType_t dumpType)
bootPart.name[4] = (u8)('0' + i); bootPart.name[4] = (u8)('0' + i);
bootPart.name[5] = 0; bootPart.name[5] = 0;
gfx_printf(&gfx_con, "%k%02d: %s (%08X-%08X)%k\n", 0xFFFFDD00, i, gfx_printf(&gfx_con, "%k%02d: %s (%07X-%07X)%k\n", 0xFFFFDD00, i,
bootPart.name, bootPart.lba_start, bootPart.lba_end, 0xFFCCCCCC); bootPart.name, bootPart.lba_start, bootPart.lba_end, 0xFFCCCCCC);
sdmmc_storage_set_mmc_partition(&storage, i+1); sdmmc_storage_set_mmc_partition(&storage, i+1);
@@ -1070,7 +1101,7 @@ static void dump_emmc_selected(dumpType_t dumpType)
if ((dumpType & DUMP_SYSTEM) == 0 && strcmp(part->name, "USER")) if ((dumpType & DUMP_SYSTEM) == 0 && strcmp(part->name, "USER"))
continue; continue;
gfx_printf(&gfx_con, "%k%02d: %s (%08X-%08X)%k\n", 0xFFFFDD00, i++, gfx_printf(&gfx_con, "%k%02d: %s (%07X-%07X)%k\n", 0xFFFFDD00, i++,
part->name, part->lba_start, part->lba_end, 0xFFCCCCCC); part->name, part->lba_start, part->lba_end, 0xFFCCCCCC);
res = dump_emmc_part(part->name, &storage, part); res = dump_emmc_part(part->name, &storage, part);
@@ -1087,7 +1118,7 @@ static void dump_emmc_selected(dumpType_t dumpType)
rawPart.lba_end = RAW_AREA_NUM_SECTORS-1; rawPart.lba_end = RAW_AREA_NUM_SECTORS-1;
strcpy(rawPart.name, "rawnand.bin"); strcpy(rawPart.name, "rawnand.bin");
{ {
gfx_printf(&gfx_con, "%k%02d: %s (%08X-%08X)%k\n", 0xFFFFDD00, i++, gfx_printf(&gfx_con, "%k%02d: %s (%07X-%07X)%k\n", 0xFFFFDD00, i++,
rawPart.name, rawPart.lba_start, rawPart.lba_end, 0xFFCCCCCC); rawPart.name, rawPart.lba_start, rawPart.lba_end, 0xFFCCCCCC);
res = dump_emmc_part(rawPart.name, &storage, &rawPart); res = dump_emmc_part(rawPart.name, &storage, &rawPart);
@@ -1099,7 +1130,7 @@ static void dump_emmc_selected(dumpType_t dumpType)
gfx_printf(&gfx_con, "Time taken: %d seconds.\n", (get_tmr() - timer) / 1000000); gfx_printf(&gfx_con, "Time taken: %d seconds.\n", (get_tmr() - timer) / 1000000);
sdmmc_storage_end(&storage); sdmmc_storage_end(&storage);
if (res) if (res)
gfx_printf(&gfx_con, "\n%kFinished and verified!%k\nPress any key...\n",0xFF00FF96, 0xFFCCCCCC); gfx_printf(&gfx_con, "\n%kFinished and verified!%k\nPress any key.\n",0xFF00FF96, 0xFFCCCCCC);
out:; out:;
btn_wait(); btn_wait();
@@ -1112,12 +1143,11 @@ void dump_emmc_rawnand() { dump_emmc_selected(DUMP_RAW); }
void dump_package1() void dump_package1()
{ {
u8 *pkg1 = (u8 *)calloc(1, 0x40000); u8 * pkg1 = (u8 *)malloc(0x40000);
u8 *warmboot = (u8 *)calloc(1, 0x40000); u8 * warmboot = (u8 *)malloc(0x40000);
u8 *secmon = (u8 *)calloc(1, 0x40000); u8 * secmon = (u8 *)malloc(0x40000);
u8 *loader = (u8 *)calloc(1, 0x40000);
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
if (!sd_mount()) if (!sd_mount())
@@ -1132,61 +1162,49 @@ void dump_package1()
} }
sdmmc_storage_set_mmc_partition(&storage, 1); sdmmc_storage_set_mmc_partition(&storage, 1);
// Read package1. //Read package1.
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1); sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1); const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20); const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
if (!pkg1_id) if (!pkg1_id)
{ {
gfx_con_setfontsz(&gfx_con, 8);
EPRINTFARGS("Could not identify package1 version to read TSEC firmware (= '%s').", (char *)pkg1 + 0x10); EPRINTFARGS("Could not identify package1 version to read TSEC firmware (= '%s').", (char *)pkg1 + 0x10);
goto out; goto out;
} }
// Read keyblob // Read keyblob
u8 * keyblob = (u8 *)malloc(NX_EMMC_BLOCKSIZE); u8 * keyblob = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + pkg1_id->kb, 1, keyblob); sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + pkg1_id->kb, 1, keyblob);
// Decrypt // decrypt
keygen(keyblob, pkg1_id->kb, (u8 *)pkg1 + pkg1_id->tsec_off); keygen(keyblob, pkg1_id->kb, (u8 *)pkg1 + pkg1_id->tsec_off);
pkg1_decrypt(pkg1_id, pkg1); pkg1_decrypt(pkg1_id, pkg1);
pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1); pkg1_unpack(warmboot, secmon, pkg1_id, pkg1);
// Display info // display info
gfx_printf(&gfx_con, "%kNX Bootloader size: %k0x%05X\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->ldr_size); gfx_printf(&gfx_con, "%kSecure monitor addr: %k%08X\n", 0xFF46EAC7, 0xFFCCCCCC, pkg1_id->secmon_base);
gfx_printf(&gfx_con, "%kNX Bootloader ofst: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->ldr_off); gfx_printf(&gfx_con, "%kSecure monitor size: %k%08X\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->sm_size);
gfx_printf(&gfx_con, "%kSecure monitor ofst: %k%08X\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->sm_off);
gfx_printf(&gfx_con, "%kSecure monitor addr: %k0x%05X\n", 0xFF46EAC7, 0xFFCCCCCC, pkg1_id->secmon_base); // dump package1
gfx_printf(&gfx_con, "%kSecure monitor size: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->sm_size); if (sd_save_to_file(pkg1, 0x40000, "pkg_decr.bin")) {
gfx_printf(&gfx_con, "%kSecure monitor ofst: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->sm_off); EPRINTF("\nFailed to create pkg_decr.bin");
gfx_printf(&gfx_con, "%kWarmboot addr: %k0x%05X\n", 0xFF46EAC7, 0xFFCCCCCC, pkg1_id->warmboot_base);
gfx_printf(&gfx_con, "%kWarmboot size: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->wb_size);
gfx_printf(&gfx_con, "%kWarmboot ofst: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->wb_off);
// Dump package1
if (sd_save_to_file(pkg1, 0x40000, "pkg1_decr.bin")) {
EPRINTF("\nFailed to create pkg1_decr.bin");
goto out; goto out;
} }
gfx_puts(&gfx_con, "\npackage1 dumped to pkg1_decr.bin\n"); gfx_puts(&gfx_con, "\npackage1 dumped to pkg_decr.bin\n");
// Dump nxbootloader // dump sm
if (sd_save_to_file(loader, hdr->ldr_size, "nxloader.bin")) { if (sd_save_to_file(secmon, 0x40000, "sm.bin")) {
EPRINTF("\nFailed to create nxloader.bin"); EPRINTF("\nFailed to create sm.bin");
goto out; goto out;
} }
gfx_puts(&gfx_con, "NX Bootloader dumped to nxloader.bin\n"); gfx_puts(&gfx_con, "Secure Monitor dumped to sm.bin\n");
// Dump secmon // dump warmboot
if (sd_save_to_file(secmon, hdr->sm_size, "secmon.bin")) { if (sd_save_to_file(warmboot, 0x40000, "warmboot.bin")) {
EPRINTF("\nFailed to create secmon.bin");
goto out;
}
gfx_puts(&gfx_con, "Secure Monitor dumped to secmon.bin\n");
// Dump warmboot
if (sd_save_to_file(warmboot, hdr->wb_size, "warmboot.bin")) {
EPRINTF("\nFailed to create warmboot.bin"); EPRINTF("\nFailed to create warmboot.bin");
goto out; goto out;
} }
@@ -1194,33 +1212,30 @@ void dump_package1()
sdmmc_storage_end(&storage); sdmmc_storage_end(&storage);
gfx_puts(&gfx_con, "\nDone. Press any key...\n"); gfx_puts(&gfx_con, "\nDone. Press any key.\n");
out:; out:;
free(pkg1); free(pkg1);
free(secmon); free(secmon);
free(warmboot); free(warmboot);
free(loader);
btn_wait(); btn_wait();
} }
void launch_firmware() void launch_firmware()
{ {
u8 max_entries = 16;
ini_sec_t *cfg_sec = NULL; ini_sec_t *cfg_sec = NULL;
LIST_INIT(ini_sections); LIST_INIT(ini_sections);
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
if (sd_mount()) if (sd_mount())
{ {
if (ini_parse(&ini_sections, "hekate_ipl.ini")) if (ini_parse(&ini_sections, "hekate_ipl.ini"))
{ {
// Build configuration menu. //Build configuration menu.
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * max_entries); ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 16);
ments[0].type = MENT_BACK; ments[0].type = MENT_BACK;
ments[0].caption = "Back"; ments[0].caption = "Back";
u32 i = 1; u32 i = 1;
@@ -1232,9 +1247,6 @@ void launch_firmware()
ments[i].caption = ini_sec->name; ments[i].caption = ini_sec->name;
ments[i].data = ini_sec; ments[i].data = ini_sec;
i++; i++;
if (i > max_entries)
break;
} }
if (i > 1) if (i > 1)
{ {
@@ -1242,18 +1254,13 @@ void launch_firmware()
menu_t menu = { menu_t menu = {
ments, "Launch configurations", 0, 0 ments, "Launch configurations", 0, 0
}; };
cfg_sec = ini_clone_section((ini_sec_t *)tui_do_menu(&gfx_con, &menu)); cfg_sec = (ini_sec_t *)tui_do_menu(&gfx_con, &menu);
if (!cfg_sec) if (!cfg_sec)
{
free(ments);
ini_free(&ini_sections);
return; return;
}
} }
else else
EPRINTF("No launch configurations found."); EPRINTF("No launch configurations found.");
free(ments); free(ments);
ini_free(&ini_sections);
} }
else else
EPRINTF("Could not find or open 'hekate_ipl.ini'.\nMake sure it exists in SD Card!."); EPRINTF("Could not find or open 'hekate_ipl.ini'.\nMake sure it exists in SD Card!.");
@@ -1261,25 +1268,27 @@ void launch_firmware()
if (!cfg_sec) if (!cfg_sec)
{ {
gfx_printf(&gfx_con, "\nUsing default launch configuration...\n");
sleep(3000000); sleep(3000000);
gfx_printf(&gfx_con, "Using default launch configuration...\n");
} }
free(Kc_HEKATE_LOGO);
if (!hos_launch(cfg_sec)) if (!hos_launch(cfg_sec))
{
Kc_HEKATE_LOGO = (u8 *)malloc(36864);
LZ_Uncompress(Kc_HEKATE_LOGOlz, Kc_HEKATE_LOGO, SZ_HEKATE_LOGOLZ);
EPRINTF("Failed to launch firmware."); EPRINTF("Failed to launch firmware.");
}
ini_free_section(cfg_sec); //TODO: free ini.
out:;
btn_wait(); btn_wait();
} }
void toggle_autorcm(){ void toggle_autorcm(){
sdmmc_storage_t storage; sdmmc_storage_t storage;
sdmmc_t sdmmc; sdmmc_t sdmmc;
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
if(!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))
{ {
EPRINTF("Failed to init eMMC."); EPRINTF("Failed to init eMMC.");
@@ -1294,95 +1303,22 @@ void toggle_autorcm(){
{ {
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE; sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
sdmmc_storage_read(&storage, sect, 1, tempbuf); sdmmc_storage_read(&storage, sect, 1, tempbuf);
tempbuf[0x10] ^= 0x77; // !IMPORTANT: DO NOT CHANGE! XOR by arbitrary number to corrupt tempbuf[0x10] ^= 0x77; //xor by arbitrary number to corrupt
sdmmc_storage_write(&storage, sect, 1, tempbuf); sdmmc_storage_write(&storage, sect, 1, tempbuf);
} }
free(tempbuf); free(tempbuf);
sdmmc_storage_end(&storage); sdmmc_storage_end(&storage);
gfx_printf(&gfx_con, "%kAutoRCM mode toggled!%k\n\nPress any key...\n", 0xFF00FF96, 0xFFCCCCCC); gfx_printf(&gfx_con, "%kAutoRCM mode toggled!%k\n", 0xFF00EE2C, 0xFFCCCCCC);
out:; out:;
btn_wait(); btn_wait();
} }
int fix_attributes(char *path, u32 *total)
{
FRESULT res;
DIR dir;
u32 i = 0;
u32 k = 0;
static FILINFO fno;
// Open directory
res = f_opendir(&dir, path);
if (res == FR_OK)
{
for (;;)
{
// Read a directory item.
res = f_readdir(&dir, &fno);
// Break on error or end of dir.
if (res != FR_OK || fno.fname[0] == 0)
break;
// Set new directory
i = strlen(path);
memcpy(&path[i], "/", 1);
for (k = 0; k < 256; k++)
{
if (fno.fname[k] == 0)
break;
}
memcpy(&path[i+1], fno.fname, k + 1);
path[i + k + 2] = 0;
// Check if archive bit is set
if (fno.fattrib & AM_ARC)
{
*(u32 *)total = *(u32 *)total + 1;
f_chmod(path, 0, AM_ARC);
}
// Is it a directory?
if (fno.fattrib & AM_DIR)
{
// Enter the directory.
res = fix_attributes(path, total);
if (res != FR_OK)
break;
}
// Clear file or folder path.
path[i] = 0;
}
f_closedir(&dir);
}
return res;
}
void fix_sd_attr(){
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
char buff[256];
u32 total = 0;
if (sd_mount())
{
gfx_printf(&gfx_con, "Traversing all sd card files!\nThis may take some time, please wait...\n");
buff[0] = '/';
buff[1] = 0;
fix_attributes(buff, &total);
gfx_printf(&gfx_con, "\n%kTotal archive bits cleared: %d!%k\n\nDone! Press any key...", 0xFF00FF96, total, 0xFFCCCCCC);
}
btn_wait();
}
void about() void about()
{ {
gfx_con_setfontsz(&gfx_con, 8);
static const char octopus[] = static const char octopus[] =
"hekate (C) 2018 naehrwert, st4rk\n\n" "hekate (C) 2018 naehrwert, st4rk\n\n"
"Thanks to: %kderrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8%k\n\n" "Thanks to: %kderrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8%k\n\n"
@@ -1409,7 +1345,7 @@ void about()
" (/` ( (` ) ) '-; %k[switchbrew]%k\n" " (/` ( (` ) ) '-; %k[switchbrew]%k\n"
" ` '-; (-'%k"; " ` '-; (-'%k";
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
gfx_con_setpos(&gfx_con, 0, 0); gfx_con_setpos(&gfx_con, 0, 0);
gfx_printf(&gfx_con, octopus, 0xFFFFCC00, 0xFFCCCCCC, gfx_printf(&gfx_con, octopus, 0xFFFFCC00, 0xFFCCCCCC,
@@ -1459,16 +1395,15 @@ ment_t ment_tools[] = {
MDEF_BACK(), MDEF_BACK(),
MDEF_CHGLINE(), MDEF_CHGLINE(),
MDEF_CAPTION("------ Full --------", 0xFFE6B90A), MDEF_CAPTION("------ Full --------", 0xFFE6B90A),
MDEF_HANDLER("Backup eMMC RAW GPP", dump_emmc_rawnand), MDEF_HANDLER("Dump RAW eMMC", dump_emmc_rawnand),
MDEF_HANDLER("Backup eMMC BOOT0/1", dump_emmc_boot), MDEF_HANDLER("Dump eMMC BOOT", dump_emmc_boot),
MDEF_CHGLINE(), MDEF_CHGLINE(),
MDEF_CAPTION("-- GPP Partitions --", 0xFFE6B90A), MDEF_CAPTION("-- GP Partitions --", 0xFFE6B90A),
MDEF_HANDLER("Backup eMMC SYS", dump_emmc_system), MDEF_HANDLER("Dump eMMC SYS", dump_emmc_system),
MDEF_HANDLER("Backup eMMC USER", dump_emmc_user), MDEF_HANDLER("Dump eMMC USER", dump_emmc_user),
MDEF_CHGLINE(), MDEF_CHGLINE(),
MDEF_CAPTION("------ Misc -------", 0xFFE6B90A), MDEF_CAPTION("------ Misc -------", 0xFFE6B90A),
MDEF_HANDLER("Dump package1", dump_package1), MDEF_HANDLER("Dump package1", dump_package1),
MDEF_HANDLER("Fix SD files attributes", fix_sd_attr),
MDEF_CHGLINE(), MDEF_CHGLINE(),
MDEF_CAPTION("---- Dangerous ----", 0xFF0000FF), MDEF_CAPTION("---- Dangerous ----", 0xFF0000FF),
MDEF_MENU("AutoRCM", &menu_autorcm), MDEF_MENU("AutoRCM", &menu_autorcm),
@@ -1495,7 +1430,7 @@ ment_t ment_top[] = {
}; };
menu_t menu_top = { menu_t menu_top = {
ment_top, ment_top,
"hekate - ipl", 0, 0 "hekate - ipl (CTCaer mod v2.2)", 0, 0
}; };
extern void pivot_stack(u32 stack_top); extern void pivot_stack(u32 stack_top);
@@ -1517,12 +1452,11 @@ void ipl_main()
//display_color_screen(0xAABBCCDD); //display_color_screen(0xAABBCCDD);
u32 *fb = display_init_framebuffer(); u32 *fb = display_init_framebuffer();
gfx_init_ctxt(&gfx_ctxt, fb, 720, 1280, 768); gfx_init_ctxt(&gfx_ctxt, fb, 720, 1280, 768);
gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_clear(&gfx_ctxt, 0xFF1B1B1B);
Kc_HEKATE_LOGO = (u8 *)malloc(36864);
LZ_Uncompress(Kc_HEKATE_LOGOlz, Kc_HEKATE_LOGO, SZ_HEKATE_LOGOLZ);
gfx_con_init(&gfx_con, &gfx_ctxt); gfx_con_init(&gfx_con, &gfx_ctxt);
// Enable backlight after initializing gfx
display_backlight(1);
while (1) while (1)
tui_do_menu(&gfx_con, &menu_top); tui_do_menu(&gfx_con, &menu_top);

View File

@@ -73,8 +73,8 @@ int max77620_regulator_get_status(u32 id)
const max77620_regulator_t *reg = &_pmic_regulators[id]; const max77620_regulator_t *reg = &_pmic_regulators[id];
if (reg->type == REGULATOR_SD) 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, 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, 0x3C, reg->cfg_addr) & 8 ? 1 : 0;
} }
int max77620_regulator_config_fps(u32 id) int max77620_regulator_config_fps(u32 id)

View File

@@ -102,7 +102,7 @@ void mc_config_carveout()
void mc_enable_ahb_redirect() void mc_enable_ahb_redirect()
{ {
CLOCK(0x3A4) = (CLOCK(0x3A4) & 0xFFF7FFFF) | 0x80000; CLOCK(0x3A4) = CLOCK(0x3A4) & 0xFFF7FFFF | 0x80000;
//MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE; //MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE;
MC(MC_IRAM_BOM) = 0x40000000; MC(MC_IRAM_BOM) = 0x40000000;
MC(MC_IRAM_TOM) = 0x4003F000; MC(MC_IRAM_TOM) = 0x4003F000;
@@ -119,13 +119,13 @@ void mc_disable_ahb_redirect()
void mc_enable() void mc_enable()
{ {
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000; 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; 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; 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_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. CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x2000001; //Clear EMC and MC reset.
sleep(5); sleep(5);

View File

@@ -37,7 +37,7 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
//HACK //HACK
for (u32 i = 0; i < 36; i++) for (u32 i = 0; i < 36; i++)
part->name[i] = ent->name[i]; part->name[i] = ent->name[i];
part->name[36] = 0; part->name[37] = 0;
list_append(gpt, &part->link); list_append(gpt, &part->link);
} }

View File

@@ -59,7 +59,7 @@ typedef struct _emmc_part_t
u32 lba_start; u32 lba_start;
u32 lba_end; u32 lba_end;
u64 attrs; u64 attrs;
s8 name[37]; u8 name[37];
link_t link; link_t link;
} emmc_part_t; } emmc_part_t;

View File

@@ -41,11 +41,6 @@
#define PINMUX_AUX_DMIC3_CLK 0xB4 #define PINMUX_AUX_DMIC3_CLK 0xB4
#define PINMUX_AUX_UART2_TX 0xF4 #define PINMUX_AUX_UART2_TX 0xF4
#define PINMUX_AUX_UART3_TX 0x104 #define PINMUX_AUX_UART3_TX 0x104
#define PINMUX_AUX_NFC_EN 0x1D0
#define PINMUX_AUX_NFC_INT 0x1D4
#define PINMUX_AUX_LCD_BL_PWM 0x1FC
#define PINMUX_AUX_LCD_BL_EN 0x200
#define PINMUX_AUX_LCD_RST 0x204
#define PINMUX_AUX_GPIO_PE6 0x248 #define PINMUX_AUX_GPIO_PE6 0x248
#define PINMUX_AUX_GPIO_PH6 0x250 #define PINMUX_AUX_GPIO_PH6 0x250
#define PINMUX_AUX_GPIO_PZ1 0x280 #define PINMUX_AUX_GPIO_PZ1 0x280

View File

@@ -16,13 +16,20 @@
#include <string.h> #include <string.h>
#include "pkg1.h" #include "pkg1.h"
#include "arm64.h"
#include "se.h" #include "se.h"
#define _ADRP(r, o) 0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F)
#define _MOVZX(r, i, s) 0xD2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F)
#define _MOVKX(r, i, s) 0xF2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F)
#define _BL(a, o) 0x94000000 | (((o) - (a)) >> 2) & 0x3FFFFFF
#define _NOP() 0xD503201F
//#define SM_100_ADR 0x40014020
#define SM_100_ADR 0x4002B020 #define SM_100_ADR 0x4002B020
PATCHSET_DEF(_secmon_1_patchset, 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)) }, { 0x1E0, _ADRP(0, 0x7C013000 - (SM_100_ADR - 0x40)) },
//Patch package2 decryption and signature/hash checks. //Patch package2 decryption and signature/hash checks.
{ 0x9F0 + 0xADC, _NOP() }, //Header signature. { 0x9F0 + 0xADC, _NOP() }, //Header signature.
{ 0x9F0 + 0xB8C, _NOP() }, //Version. { 0x9F0 + 0xB8C, _NOP() }, //Version.
@@ -38,26 +45,53 @@ PATCHSET_DEF(_secmon_2_patchset,
PATCHSET_DEF(_secmon_3_patchset, PATCHSET_DEF(_secmon_3_patchset,
//Patch package2 decryption and signature/hash checks. //Patch package2 decryption and signature/hash checks.
{ 0xAC8 + 0xAB4, _NOP() },
{ 0xAC8 + 0xA30, _NOP() }, //Header signature. { 0xAC8 + 0xA30, _NOP() }, //Header signature.
{ 0xAC8 + 0xAB4, _NOP() }, //package2 structure.
{ 0xAC8 + 0xAC0, _NOP() }, //Version. { 0xAC8 + 0xAC0, _NOP() }, //Version.
{ 0xAC8 + 0xADC, _NOP() } //Sections SHA2. { 0xAC8 + 0xADC, _NOP() } //Sections SHA2.
); );
PATCHSET_DEF(_secmon_4_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. { 0x1218 + 0x6E68, _NOP() }, //Header signature.
{ 0x2300 + 0x5D8C, _NOP() }, //Version. { 0x1218 + 0x6E74, _NOP() }, //Version.
{ 0x2300 + 0x5EFC, _NOP() }, //Header signature. { 0x1218 + 0x6FE4, _NOP() }, //Sections SHA2.
{ 0xAC8 + 0xA2C, _NOP() } //Sections SHA2. { 0x1218 + 0x2DC, _NOP() } //Unknown.
); );
PATCHSET_DEF(_secmon_5_patchset, PATCHSET_DEF(_secmon_5_patchset,
//Patch package2 decryption and signature/hash checks. //Patch package2 decryption and signature/hash checks.
{ 0xDA8 + 0x9D8 , _NOP() }, //package2 structure. { 0x12b0 + 0x4d0, _NOP() },
{ 0xDA8 + 0x9E4 , _NOP() }, //Version. { 0x12b0 + 0x4dc, _NOP() },
{ 0xDA8 + 0xC9C , _NOP() }, //Header signature. { 0x12b0 + 0x794, _NOP() },
{ 0xDA8 + 0x1038 , _NOP() } //Sections SHA2. { 0x12b0 + 0xb30, _NOP() }//,
//{ 0x12b0 + 0xa18 , _NOP() } // BootConfig Retail Check
);
// Include kernel patches here, so we can utilize pkg1 id
PATCHSET_DEF(_kernel_1_patchset,
{ 0x3764C, _NOP() }, // Disable SVC verifications
{ 0x44074, _MOVZX(8, 1, 0) } // Enable Debug Patch
);
PATCHSET_DEF(_kernel_2_patchset,
{ 0x54834, _NOP() }, // Disable SVC verifications
{ 0x6086C, _MOVZX(8, 1, 0) } // Enable Debug Patch
);
PATCHSET_DEF(_kernel_3_patchset,
{ 0x3BD24, _NOP() }, // Disable SVC verifications
{ 0x483FC, _MOVZX(8, 1, 0) } // Enable Debug Patch
);
PATCHSET_DEF(_kernel_4_patchset,
{ 0x41EB4, _NOP() }, // Disable SVC verifications
{ 0x4EBFC, _MOVZX(8, 1, 0) } // Enable Debug Patch
);
PATCHSET_DEF(_kernel_5_patchset,
{ 0x45E6C, _NOP() }, // Disable SVC verifications
{ 0x5513C, _MOVZX(8, 1, 0) } // Enable Debug Patch
); );
/* /*
@@ -72,13 +106,13 @@ PATCHSET_DEF(_secmon_5_patchset,
*/ */
static const pkg1_id_t _pkg1_ids[] = { 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) { "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, _secmon_1_patchset, _kernel_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 { "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_2_patchset, _kernel_2_patchset }, //2.0.0 - 2.3.0
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_3_patchset }, //3.0.0 { "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_3_patchset, _kernel_3_patchset }, //3.0.0
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1, _secmon_3_patchset }, //3.0.1 - 3.0.2 { "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_3_patchset, _kernel_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 { "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_4_patchset, _kernel_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 { "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_5_patchset, _kernel_5_patchset }, //5.0.0 - 5.0.2
{ NULL } //End. { NULL, 0, 0, 0, 0 } //End.
}; };
@@ -98,7 +132,7 @@ void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
se_aes_crypt_ctr(11, pkg11 + 0x20, pkg11_size, pkg11 + 0x20, pkg11_size, pkg11 + 0x10); se_aes_crypt_ctr(11, pkg11 + 0x20, pkg11_size, pkg11 + 0x20, pkg11_size, pkg11 + 0x10);
} }
void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1) void pkg1_unpack(void *warmboot_dst, void *secmon_dst, const pkg1_id_t *id, u8 *pkg1)
{ {
pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20); pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20);
@@ -110,8 +144,6 @@ void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1
{ {
if (id->sec_map[i] == 0 && warmboot_dst) if (id->sec_map[i] == 0 && warmboot_dst)
memcpy(warmboot_dst, pdata, sec_size[id->sec_map[i]]); memcpy(warmboot_dst, pdata, sec_size[id->sec_map[i]]);
else if (id->sec_map[i] == 1 && ldr_dst)
memcpy(ldr_dst, pdata, sec_size[id->sec_map[i]]);
else if (id->sec_map[i] == 2 && secmon_dst) else if (id->sec_map[i] == 2 && secmon_dst)
memcpy(secmon_dst, pdata, sec_size[id->sec_map[i]]); memcpy(secmon_dst, pdata, sec_size[id->sec_map[i]]);
pdata += sec_size[id->sec_map[i]]; pdata += sec_size[id->sec_map[i]];

View File

@@ -25,6 +25,12 @@
{ 0xFFFFFFFF, 0xFFFFFFFF } \ { 0xFFFFFFFF, 0xFFFFFFFF } \
} }
typedef struct _patch_t
{
u32 off;
u32 val;
} patch_t;
typedef struct _pkg1_id_t typedef struct _pkg1_id_t
{ {
const char *id; const char *id;
@@ -33,9 +39,8 @@ typedef struct _pkg1_id_t
u32 pkg11_off; u32 pkg11_off;
u32 sec_map[3]; u32 sec_map[3];
u32 secmon_base; u32 secmon_base;
u32 warmboot_base;
int set_warmboot;
patch_t *secmon_patchset; patch_t *secmon_patchset;
patch_t *kernel_patchset;
} pkg1_id_t; } pkg1_id_t;
typedef struct _pk11_hdr_t typedef struct _pk11_hdr_t
@@ -52,6 +57,6 @@ typedef struct _pk11_hdr_t
const pkg1_id_t *pkg1_identify(u8 *pkg1); const pkg1_id_t *pkg1_identify(u8 *pkg1);
void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1); void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1); void pkg1_unpack(void *warmboot_dst, void *secmon_dst, const pkg1_id_t *id, u8 *pkg1);
#endif #endif

View File

@@ -16,7 +16,6 @@
#include <string.h> #include <string.h>
#include "pkg2.h" #include "pkg2.h"
#include "arm64.h"
#include "heap.h" #include "heap.h"
#include "se.h" #include "se.h"
@@ -26,55 +25,6 @@ extern gfx_con_t gfx_con;
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/ #define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/
#define DPRINTF(...) #define DPRINTF(...)
// Include kernel patches here, so we can utilize pkg1 id
PATCHSET_DEF(_kernel_1_patchset,
{ 0x3764C, _NOP() }, // Disable SVC verifications
{ 0x44074, _MOVZX(8, 1, 0) } // Enable Debug Patch
);
PATCHSET_DEF(_kernel_2_patchset,
{ 0x54834, _NOP() }, // Disable SVC verifications
{ 0x6086C, _MOVZX(8, 1, 0) } // Enable Debug Patch
);
PATCHSET_DEF(_kernel_3_patchset,
{ 0x3BD24, _NOP() }, // Disable SVC verifications
{ 0x483FC, _MOVZX(8, 1, 0) } // Enable Debug Patch
);
PATCHSET_DEF(_kernel_302_patchset,
{ 0x3BD24, _NOP() }, // Disable SVC verifications
{ 0x48414, _MOVZX(8, 1, 0) } // Enable Debug Patch
);
PATCHSET_DEF(_kernel_4_patchset,
{ 0x41EB4, _NOP() }, // Disable SVC verifications
{ 0x4EBFC, _MOVZX(8, 1, 0) } // Enable Debug Patch
);
PATCHSET_DEF(_kernel_5_patchset,
{ 0x45E6C, _NOP() }, // Disable SVC verifications
{ 0x5513C, _MOVZX(8, 1, 0) } // Enable Debug Patch
);
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
{ 0, 0 } //End.
};
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) static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1)
{ {
u32 size = sizeof(pkg2_kip1_t); u32 size = sizeof(pkg2_kip1_t);

View File

@@ -27,12 +27,6 @@
#define INI1_MAGIC 0x31494E49 #define INI1_MAGIC 0x31494E49
#define PATCHSET_DEF(name, ...) \
patch_t name[] = { \
__VA_ARGS__, \
{ 0xFFFFFFFF, 0xFFFFFFFF } \
}
typedef struct _pkg2_hdr_t typedef struct _pkg2_hdr_t
{ {
u8 ctr[0x10]; u8 ctr[0x10];
@@ -88,19 +82,12 @@ typedef struct _pkg2_kip1_info_t
link_t link; link_t link;
} pkg2_kip1_info_t; } pkg2_kip1_info_t;
typedef struct _pkg2_kernel_id_t
{
u32 crc32c_id;
patch_t *kernel_patchset;
} pkg2_kernel_id_t;
void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2); void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2);
int pkg2_has_kip(link_t *info, u64 tid); int pkg2_has_kip(link_t *info, u64 tid);
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1); 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_add_kip(link_t *info, pkg2_kip1_t *kip1);
void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1); void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1);
const pkg2_kernel_id_t *pkg2_identify(u32 id);
pkg2_hdr_t *pkg2_decrypt(void *data); pkg2_hdr_t *pkg2_decrypt(void *data);
void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info); void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info);

View File

@@ -174,7 +174,8 @@ static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 nu
else else
retries--; retries--;
sleep(100000); sleep(500000);
} while (retries); } while (retries);
return 0; return 0;
@@ -307,7 +308,7 @@ static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
} }
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf) static int _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
{ {
storage->ext_csd.rev = buf[EXT_CSD_REV]; storage->ext_csd.rev = buf[EXT_CSD_REV];
storage->ext_csd.ext_struct = buf[EXT_CSD_STRUCTURE]; storage->ext_csd.ext_struct = buf[EXT_CSD_STRUCTURE];
@@ -433,9 +434,9 @@ static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type
return _mmc_storage_enable_HS400(storage); return _mmc_storage_enable_HS400(storage);
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 || if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 ||
(sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_4 sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_4
&& card_type & EXT_CSD_CARD_TYPE_HS200_1_8V && card_type & EXT_CSD_CARD_TYPE_HS200_1_8V
&& (type == 4 || type == 3))) && (type == 4 || type == 3))
return _mmc_storage_enable_HS200(storage); return _mmc_storage_enable_HS200(storage);
out:; out:;
@@ -767,12 +768,12 @@ int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf)
if (type_out != hs_type) if (type_out != hs_type)
return 0; return 0;
if ((((u16)buf[0] << 8) | buf[1]) < 0x320) if (((u16)buf[0] << 8) | buf[1] < 0x320)
{ {
if (!_sd_storage_switch(storage, buf, 1, hs_type)) if (!_sd_storage_switch(storage, buf, 1, hs_type))
return 0; return 0;
if (type_out != (buf[16] & 0xF)) if (type_out != buf[16] & 0xF)
return 0; return 0;
} }
@@ -849,7 +850,7 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20]; raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16]; raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1; storage->ssr.bus_width = unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4 ? 4 : 1;
switch(unstuff_bits(raw_ssr1, 440 - 384, 8)) switch(unstuff_bits(raw_ssr1, 440 - 384, 8))
{ {
case 0: case 0:

View File

@@ -129,7 +129,7 @@ static int _sdmmc_config_ven_ceata_clk(sdmmc_t *sdmmc, u32 id)
static const u32 tap_values[] = { 4, 0, 3, 0 }; static const u32 tap_values[] = { 4, 0, 3, 0 };
tap_val = tap_values[sdmmc->id]; tap_val = tap_values[sdmmc->id];
} }
sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (tap_val << 16); sdmmc->regs->venclkctl = sdmmc->regs->venclkctl & 0xFF00FFFF | (tap_val << 16);
return 1; return 1;
} }
@@ -624,7 +624,7 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power)
break; break;
} }
sdmmc->regs->autocalcfg = (((sdmmc->regs->autocalcfg & 0xFFFF80FF) | (off_pd << 8)) >> 7 << 7) | off_pu; sdmmc->regs->autocalcfg = ((sdmmc->regs->autocalcfg & 0xFFFF80FF | (off_pd << 8)) >> 7 << 7) | off_pu;
return 1; return 1;
} }

View File

@@ -64,7 +64,7 @@ static void _sdram_config(const sdram_params_t *params)
sleep(10); sleep(10);
break_nosleep: break_nosleep:
CLOCK(0x19C) = ((params->mc_emem_arb_misc0 >> 11) & 0x10000) | (params->emc_clock_source & 0xFFFEFFFF); CLOCK(0x19C) = (params->mc_emem_arb_misc0 >> 11) & 0x10000 | params->emc_clock_source & 0xFFFEFFFF;
if (params->emc_clock_source_dll) if (params->emc_clock_source_dll)
CLOCK(0x664) = params->emc_clock_source_dll; CLOCK(0x664) = params->emc_clock_source_dll;
if (params->clear_clock2_mc1) if (params->clear_clock2_mc1)
@@ -97,7 +97,7 @@ break_nosleep:
EMC(EMC_PMACRO_BRICK_MAPPING_0) = params->emc_pmacro_brick_mapping0; EMC(EMC_PMACRO_BRICK_MAPPING_0) = params->emc_pmacro_brick_mapping0;
EMC(EMC_PMACRO_BRICK_MAPPING_1) = params->emc_pmacro_brick_mapping1; EMC(EMC_PMACRO_BRICK_MAPPING_1) = params->emc_pmacro_brick_mapping1;
EMC(EMC_PMACRO_BRICK_MAPPING_2) = params->emc_pmacro_brick_mapping2; EMC(EMC_PMACRO_BRICK_MAPPING_2) = params->emc_pmacro_brick_mapping2;
EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = (params->emc_pmacro_brick_ctrl_rfu1 & 0x1120112) | 0x1EED1EED; EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1 & 0x1120112 | 0x1EED1EED;
EMC(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay; EMC(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay;
EMC(EMC_FBIO_CFG8) = params->emc_fbio_cfg8; EMC(EMC_FBIO_CFG8) = params->emc_fbio_cfg8;
EMC(EMC_SWIZZLE_RANK0_BYTE0) = params->emc_swizzle_rank0_byte0; EMC(EMC_SWIZZLE_RANK0_BYTE0) = params->emc_swizzle_rank0_byte0;
@@ -142,7 +142,7 @@ break_nosleep:
EMC(EMC_QUSE_BRLSHFT_1) = params->emc_quse_brlshft1; EMC(EMC_QUSE_BRLSHFT_1) = params->emc_quse_brlshft1;
EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2; EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2;
EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3; EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3;
EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = (params->emc_pmacro_brick_ctrl_rfu1 & 0x1BF01BF) | 0x1E401E40; EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1 & 0x1BF01BF | 0x1E401E40;
EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl; EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl;
EMC(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd; EMC(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd;
EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2 & 0xFF7FFF7F; EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2 & 0xFF7FFF7F;
@@ -232,7 +232,7 @@ break_nosleep:
EMC(EMC_PMACRO_DDLL_SHORT_CMD_0) = params->emc_pmacro_ddll_short_cmd_0; EMC(EMC_PMACRO_DDLL_SHORT_CMD_0) = params->emc_pmacro_ddll_short_cmd_0;
EMC(EMC_PMACRO_DDLL_SHORT_CMD_1) = params->emc_pmacro_ddll_short_cmd_1; EMC(EMC_PMACRO_DDLL_SHORT_CMD_1) = params->emc_pmacro_ddll_short_cmd_1;
EMC(EMC_PMACRO_DDLL_SHORT_CMD_2) = params->emc_pmacro_ddll_short_cmd_2; EMC(EMC_PMACRO_DDLL_SHORT_CMD_2) = params->emc_pmacro_ddll_short_cmd_2;
EMC(EMC_PMACRO_COMMON_PAD_TX_CTRL) = (params->emc_pmacro_common_pad_tx_ctrl & 1) | 0xE; EMC(EMC_PMACRO_COMMON_PAD_TX_CTRL) = params->emc_pmacro_common_pad_tx_ctrl & 1 | 0xE;
if (params->emc_bct_spare4) if (params->emc_bct_spare4)
*(vu32 *)params->emc_bct_spare4 = params->emc_bct_spare5; *(vu32 *)params->emc_bct_spare4 = params->emc_bct_spare5;
EMC(EMC_TIMING_CONTROL) = 1; EMC(EMC_TIMING_CONTROL) = 1;
@@ -386,7 +386,7 @@ break_nosleep:
EMC(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3; EMC(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3;
EMC(EMC_ACPD_CONTROL) = params->emc_acpd_control; EMC(EMC_ACPD_CONTROL) = params->emc_acpd_control;
EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen; EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen;
EMC(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000; EMC(EMC_CFG) = params->emc_cfg & 0xE | 0x3C00000;
if (params->boot_rom_patch_control & 0x80000000) if (params->boot_rom_patch_control & 0x80000000)
{ {
*(vu32 *)(4 * (params->boot_rom_patch_control + 0x1C000000)) = params->boot_rom_patch_data; *(vu32 *)(4 * (params->boot_rom_patch_control + 0x1C000000)) = params->boot_rom_patch_data;
@@ -481,7 +481,7 @@ break_nosleep:
EMC(EMC_TIMING_CONTROL) = 1; EMC(EMC_TIMING_CONTROL) = 1;
EMC(EMC_CFG_PIPE_CLK) = params->emc_cfg_pipe_clk; EMC(EMC_CFG_PIPE_CLK) = params->emc_cfg_pipe_clk;
EMC(EMC_FDPD_CTRL_CMD_NO_RAMP) = params->emc_fdpd_ctrl_cmd_no_ramp; EMC(EMC_FDPD_CTRL_CMD_NO_RAMP) = params->emc_fdpd_ctrl_cmd_no_ramp;
SYSREG(AHB_ARBITRATION_XBAR_CTRL) = (SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF) | ((params->ahb_arbitration_xbar_ctrl_meminit_done & 0xFFFF) << 16); SYSREG(AHB_ARBITRATION_XBAR_CTRL) = SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF | ((params->ahb_arbitration_xbar_ctrl_meminit_done & 0xFFFF) << 16);
MC(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access; MC(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access;
MC(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access; MC(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access;
MC(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl; MC(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl;

View File

@@ -23,7 +23,7 @@
*/ */
void sdram_lp0_save_params(const void *params) void sdram_lp0_save_params(const void *params)
{ {
struct sdram_params *sdram = (struct sdram_params *)params; const struct sdram_params *sdram = (const struct sdram_params *)params;
struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs *)PMC_BASE; struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs *)PMC_BASE;
#define pack(src, src_bits, dst, dst_bits) { \ #define pack(src, src_bits, dst, dst_bits) { \
@@ -44,100 +44,6 @@ void sdram_lp0_save_params(const void *params)
/* 32 bits version c macro */ /* 32 bits version c macro */
#define c32(value, pmcreg) pmc->pmcreg = value #define c32(value, pmcreg) pmc->pmcreg = value
//TODO: pkg1.1 (1.X - 3.X) reads them from MC.
//Patch carveout parameters.
/*sdram->McGeneralizedCarveout1Bom = 0;
sdram->McGeneralizedCarveout1BomHi = 0;
sdram->McGeneralizedCarveout1Size128kb = 0;
sdram->McGeneralizedCarveout1Access0 = 0;
sdram->McGeneralizedCarveout1Access1 = 0;
sdram->McGeneralizedCarveout1Access2 = 0;
sdram->McGeneralizedCarveout1Access3 = 0;
sdram->McGeneralizedCarveout1Access4 = 0;
sdram->McGeneralizedCarveout1ForceInternalAccess0 = 0;
sdram->McGeneralizedCarveout1ForceInternalAccess1 = 0;
sdram->McGeneralizedCarveout1ForceInternalAccess2 = 0;
sdram->McGeneralizedCarveout1ForceInternalAccess3 = 0;
sdram->McGeneralizedCarveout1ForceInternalAccess4 = 0;
sdram->McGeneralizedCarveout1Cfg0 = 0;
sdram->McGeneralizedCarveout2Bom = 0x80020000;
sdram->McGeneralizedCarveout2BomHi = 0;
sdram->McGeneralizedCarveout2Size128kb = 2;
sdram->McGeneralizedCarveout2Access0 = 0;
sdram->McGeneralizedCarveout2Access1 = 0;
sdram->McGeneralizedCarveout2Access2 = 0x3000000;
sdram->McGeneralizedCarveout2Access3 = 0;
sdram->McGeneralizedCarveout2Access4 = 0x300;
sdram->McGeneralizedCarveout2ForceInternalAccess0 = 0;
sdram->McGeneralizedCarveout2ForceInternalAccess1 = 0;
sdram->McGeneralizedCarveout2ForceInternalAccess2 = 0;
sdram->McGeneralizedCarveout2ForceInternalAccess3 = 0;
sdram->McGeneralizedCarveout2ForceInternalAccess4 = 0;
sdram->McGeneralizedCarveout2Cfg0 = 0x440167E;
sdram->McGeneralizedCarveout3Bom = 0;
sdram->McGeneralizedCarveout3BomHi = 0;
sdram->McGeneralizedCarveout3Size128kb = 0;
sdram->McGeneralizedCarveout3Access0 = 0;
sdram->McGeneralizedCarveout3Access1 = 0;
sdram->McGeneralizedCarveout3Access2 = 0x3000000;
sdram->McGeneralizedCarveout3Access3 = 0;
sdram->McGeneralizedCarveout3Access4 = 0x300;
sdram->McGeneralizedCarveout3ForceInternalAccess0 = 0;
sdram->McGeneralizedCarveout3ForceInternalAccess1 = 0;
sdram->McGeneralizedCarveout3ForceInternalAccess2 = 0;
sdram->McGeneralizedCarveout3ForceInternalAccess3 = 0;
sdram->McGeneralizedCarveout3ForceInternalAccess4 = 0;
sdram->McGeneralizedCarveout3Cfg0 = 0x4401E7E;
sdram->McGeneralizedCarveout4Bom = 0;
sdram->McGeneralizedCarveout4BomHi = 0;
sdram->McGeneralizedCarveout4Size128kb = 0;
sdram->McGeneralizedCarveout4Access0 = 0;
sdram->McGeneralizedCarveout4Access1 = 0;
sdram->McGeneralizedCarveout4Access2 = 0;
sdram->McGeneralizedCarveout4Access3 = 0;
sdram->McGeneralizedCarveout4Access4 = 0;
sdram->McGeneralizedCarveout4ForceInternalAccess0 = 0;
sdram->McGeneralizedCarveout4ForceInternalAccess1 = 0;
sdram->McGeneralizedCarveout4ForceInternalAccess2 = 0;
sdram->McGeneralizedCarveout4ForceInternalAccess3 = 0;
sdram->McGeneralizedCarveout4ForceInternalAccess4 = 0;
sdram->McGeneralizedCarveout4Cfg0 = 0x8F;
sdram->McGeneralizedCarveout5Bom = 0;
sdram->McGeneralizedCarveout5BomHi = 0;
sdram->McGeneralizedCarveout5Size128kb = 0;
sdram->McGeneralizedCarveout5Access0 = 0;
sdram->McGeneralizedCarveout5Access1 = 0;
sdram->McGeneralizedCarveout5Access2 = 0;
sdram->McGeneralizedCarveout5Access3 = 0;
sdram->McGeneralizedCarveout5Access4 = 0;
sdram->McGeneralizedCarveout5ForceInternalAccess0 = 0;
sdram->McGeneralizedCarveout5ForceInternalAccess1 = 0;
sdram->McGeneralizedCarveout5ForceInternalAccess2 = 0;
sdram->McGeneralizedCarveout5ForceInternalAccess3 = 0;
sdram->McGeneralizedCarveout5ForceInternalAccess4 = 0;
sdram->McGeneralizedCarveout5Cfg0 = 0x8F;*/
//TODO: this is 4.X+ behaviour which seems to work fine for < 4.X.
//Patch carveout parameters.
sdram->McGeneralizedCarveout1Cfg0 = 0;
sdram->McGeneralizedCarveout2Cfg0 = 0;
sdram->McGeneralizedCarveout3Cfg0 = 0;
sdram->McGeneralizedCarveout4Cfg0 = 0;
sdram->McGeneralizedCarveout5Cfg0 = 0;
//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);
u32 t3 = (t2 & 0xFFFFFFDF) | ((sdram->EmcSwizzleRank1Byte1 << 5 >> 29 > sdram->EmcSwizzleRank1Byte1 << 1 >> 29) << 5);
u32 t4 = (t3 & 0xFFFFFFFB) | ((sdram->EmcSwizzleRank0Byte2 << 5 >> 29 > sdram->EmcSwizzleRank0Byte2 << 1 >> 29) << 2);
u32 t5 = (t4 & 0xFFFFFFBF) | ((sdram->EmcSwizzleRank1Byte2 << 5 >> 29 > sdram->EmcSwizzleRank1Byte2 << 1 >> 29) << 6);
u32 t6 = (t5 & 0xFFFFFFF7) | ((sdram->EmcSwizzleRank0Byte3 << 5 >> 29 > sdram->EmcSwizzleRank0Byte3 << 1 >> 29) << 3);
u32 t7 = (t6 & 0xFFFFFF7F) | ((sdram->EmcSwizzleRank1Byte3 << 5 >> 29 > sdram->EmcSwizzleRank1Byte3 << 1 >> 29) << 7);
sdram->SwizzleRankByteEncode = t7;
sdram->EmcBctSpare2 = 0x40000DD8;
sdram->EmcBctSpare3 = t7;
s(EmcClockSource, 7:0, scratch6, 15:8); s(EmcClockSource, 7:0, scratch6, 15:8);
s(EmcClockSourceDll, 7:0, scratch6, 23:16); s(EmcClockSourceDll, 7:0, scratch6, 23:16);
s(EmcClockSource, 31:29, scratch6, 26:24); s(EmcClockSource, 31:29, scratch6, 26:24);
@@ -808,7 +714,7 @@ void sdram_lp0_save_params(const void *params)
s32(EmcBctSpare6, scratch40); s32(EmcBctSpare6, scratch40);
s32(EmcBctSpare5, scratch42); s32(EmcBctSpare5, scratch42);
s32(EmcBctSpare4, scratch44); s32(EmcBctSpare4, scratch44);
s32(EmcBctSpare3, scratch45); s32(SwizzleRankByteEncode, scratch45);
s32(EmcBctSpare2, scratch46); s32(EmcBctSpare2, scratch46);
s32(EmcBctSpare1, scratch47); s32(EmcBctSpare1, scratch47);
s32(EmcBctSpare0, scratch48); s32(EmcBctSpare0, scratch48);
@@ -1098,6 +1004,11 @@ void sdram_lp0_save_params(const void *params)
s32(McGeneralizedCarveout5ForceInternalAccess2, secure_scratch106); s32(McGeneralizedCarveout5ForceInternalAccess2, secure_scratch106);
s32(McGeneralizedCarveout5ForceInternalAccess3, secure_scratch107); s32(McGeneralizedCarveout5ForceInternalAccess3, secure_scratch107);
/* Locking PMC secure scratch register (8 ~ 15) for writing */
//c(0x5555, sec_disable2, 15:0);
/* Locking PMC secure scratch register (4~ 7) for both reading and writing */
//c(0xff, sec_disable, 19:12);
c32(0, scratch2); c32(0, scratch2);
s(PllMInputDivider, 7:0, scratch2, 7:0); s(PllMInputDivider, 7:0, scratch2, 7:0);
s(PllMFeedbackDivider, 7:0, scratch2, 15:8); s(PllMFeedbackDivider, 7:0, scratch2, 15:8);

View File

@@ -124,7 +124,7 @@ static void _se_aes_ctr_set(void *ctr)
void se_rsa_acc_ctrl(u32 rs, u32 flags) void se_rsa_acc_ctrl(u32 rs, u32 flags)
{ {
if (flags & 0x7F) if (flags & 0x7F)
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = (((flags >> 4) & 4) | (flags & 3)) ^ 7; SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = ((flags >> 4) & 4 | flags & 3) ^ 7;
if (flags & 0x80) if (flags & 0x80)
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs); SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs);
} }

View File

@@ -17,6 +17,8 @@
#include "tui.h" #include "tui.h"
#include "btn.h" #include "btn.h"
extern u8 *Kc_HEKATE_LOGO;
void tui_pbar(gfx_con_t *con, int x, int y, u32 val, u32 fgcol, u32 bgcol) void tui_pbar(gfx_con_t *con, int x, int y, u32 val, u32 fgcol, u32 bgcol)
{ {
u32 cx, cy; u32 cx, cy;
@@ -27,9 +29,9 @@ void tui_pbar(gfx_con_t *con, int x, int y, u32 val, u32 fgcol, u32 bgcol)
gfx_printf(con, "%k[%3d%%]%k", fgcol, val, 0xFFCCCCCC); gfx_printf(con, "%k[%3d%%]%k", fgcol, val, 0xFFCCCCCC);
x += 7 * 8; x += 7 * con->fntsz;
for (int i = 0; i < 6; i++) for (int i = 0; i < con->fontmult * 6; i++)
{ {
gfx_line(con->gfx_ctxt, x, y + i + 1, x + 3 * val, y + i + 1, fgcol); gfx_line(con->gfx_ctxt, x, y + i + 1, x + 3 * val, y + i + 1, fgcol);
gfx_line(con->gfx_ctxt, x + 3 * val, y + i + 1, x + 3 * 100, y + i + 1, bgcol); gfx_line(con->gfx_ctxt, x + 3 * val, y + i + 1, x + 3 * 100, y + i + 1, bgcol);
@@ -40,9 +42,11 @@ 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) void *tui_do_menu(gfx_con_t *con, menu_t *menu)
{ {
int idx = 0, prev_idx = 0, cnt = 0x7FFFFFFF; int idx = 0, cnt;
int prev_idx = 0;
gfx_clear_grey(con->gfx_ctxt, 0x1B); gfx_clear(con->gfx_ctxt, 0xFF1B1B1B);
gfx_set_logo(con->gfx_ctxt, Kc_HEKATE_LOGO);
while (1) while (1)
{ {
@@ -50,12 +54,12 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
gfx_con_setpos(con, menu->x, menu->y); gfx_con_setpos(con, menu->x, menu->y);
gfx_printf(con, "[%s]\n\n", menu->caption); gfx_printf(con, "[%s]\n\n", menu->caption);
// Skip caption or seperator lines selection. // Skip caption or seperator lines selection
while (menu->ents[idx].type == MENT_CAPTION || while (menu->ents[idx].type == MENT_CAPTION ||
menu->ents[idx].type == MENT_CHGLINE) menu->ents[idx].type == MENT_CHGLINE)
{ {
if (prev_idx <= idx || (!idx && prev_idx == cnt - 1)) if (prev_idx <= idx || (!idx && prev_idx == cnt - 1))
{ {
idx++; idx++;
if (idx > (cnt - 1)) if (idx > (cnt - 1))
{ {
@@ -75,16 +79,16 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
} }
prev_idx = idx; prev_idx = idx;
//Draw the menu. // Draw the menu
for (cnt = 0; menu->ents[cnt].type != MENT_END; cnt++) for (cnt = 0; menu->ents[cnt].type != MENT_END; cnt++)
{ {
if (cnt == idx) if (cnt == idx)
gfx_con_setcol(con, 0xFF1B1B1B, 1, 0xFFCCCCCC); gfx_con_setcol(con, 0xFF1B1B1B, 1, 0xFFCCCCCC);
else else
gfx_con_setcol(con, 0xFFCCCCCC, 1, 0xFF1B1B1B); gfx_con_setcol(con, 0xFFCCCCCC, 1, 0xFF1B1B1B);
if (menu->ents[cnt].type == MENT_CAPTION) if (cnt != idx && menu->ents[cnt].type == MENT_CAPTION)
gfx_printf(con, "%k %s", menu->ents[cnt].color, menu->ents[cnt].caption); gfx_printf(con, "%k %s", menu->ents[cnt].color, menu->ents[cnt].caption);
else if (menu->ents[cnt].type != MENT_CHGLINE) else
gfx_printf(con, " %s", menu->ents[cnt].caption); gfx_printf(con, " %s", menu->ents[cnt].caption);
if(menu->ents[cnt].type == MENT_MENU) if(menu->ents[cnt].type == MENT_MENU)
gfx_printf(con, "%k...", 0xFFEE9900); gfx_printf(con, "%k...", 0xFFEE9900);
@@ -123,7 +127,9 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
default: default:
break; break;
} }
gfx_clear_grey(con->gfx_ctxt, 0x1B); gfx_con_setfontsz(con, 16);
gfx_clear(con->gfx_ctxt, 0xFF1B1B1B);
gfx_set_logo(con->gfx_ctxt, Kc_HEKATE_LOGO);
} }
} }

View File

@@ -26,10 +26,6 @@
#define OFFSET_OF(t, m) ((u32)&((t *)NULL)->m) #define OFFSET_OF(t, m) ((u32)&((t *)NULL)->m)
#define CONTAINER_OF(mp, t, mn) ((t *)((u32)mp - OFFSET_OF(t, mn))) #define CONTAINER_OF(mp, t, mn) ((t *)((u32)mp - OFFSET_OF(t, mn)))
typedef char s8;
typedef short s16;
typedef int s32;
typedef long long int s64;
typedef unsigned char u8; typedef unsigned char u8;
typedef unsigned short u16; typedef unsigned short u16;
typedef unsigned int u32; typedef unsigned int u32;
@@ -38,10 +34,4 @@ typedef volatile unsigned char vu8;
typedef volatile unsigned short vu16; typedef volatile unsigned short vu16;
typedef volatile unsigned int vu32; typedef volatile unsigned int vu32;
typedef struct _patch_t
{
u32 off;
u32 val;
} patch_t;
#endif #endif

View File

@@ -35,16 +35,3 @@ void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops)
base[ops[i].off] = ops[i].val; base[ops[i].off] = ops[i].val;
} }
#define CRC32C_POLY 0x82F63B78
u32 crc32c(const void *buf, u32 len)
{
const u8 *cbuf = (const u8 *)buf;
u32 crc = 0xFFFFFFFF;
while (len--)
{
crc ^= *cbuf++;
for (int i = 0; i < 8; i++)
crc = crc & 1 ? (crc >> 1) ^ CRC32C_POLY : crc >> 1;
}
return ~crc;
}

View File

@@ -28,6 +28,5 @@ typedef struct _cfg_op_t
u32 get_tmr(); u32 get_tmr();
void sleep(u32 ticks); void sleep(u32 ticks);
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u32 crc32c(const void *buf, u32 len);
#endif #endif