mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 19:31:12 +00:00
commit
36bd3bbed1
19 changed files with 280 additions and 153 deletions
35
ipl/arm64.h
Executable file
35
ipl/arm64.h
Executable file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ARM64_H_
|
||||
#define _ARM64_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define LSL0 0
|
||||
#define LSL16 16
|
||||
#define LSL32 32
|
||||
|
||||
#define _PAGEOFF(x) ((x) & 0xFFFFF000)
|
||||
|
||||
#define _ADRP(r, o) 0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F)
|
||||
#define _BL(a, o) 0x94000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF)
|
||||
#define _B(a, o) 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
|
29
ipl/btn.c
29
ipl/btn.c
|
@ -18,6 +18,7 @@
|
|||
#include "i2c.h"
|
||||
#include "gpio.h"
|
||||
#include "t210.h"
|
||||
#include "util.h"
|
||||
|
||||
u32 btn_read()
|
||||
{
|
||||
|
@ -36,22 +37,38 @@ u32 btn_wait()
|
|||
u32 res = 0, btn = btn_read();
|
||||
int pwr = 0;
|
||||
|
||||
// Power button down, raise a filter.
|
||||
//Power button down, raise a filter.
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
pwr = 1;
|
||||
btn &= 0xFFFFFFFE;
|
||||
btn &= ~BTN_POWER;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
res = btn_read();
|
||||
// Power button up, remove filter.
|
||||
//Power button up, remove filter.
|
||||
if (!(res & BTN_POWER) && pwr)
|
||||
pwr = 0;
|
||||
// Power button still down.
|
||||
else if (pwr)
|
||||
res &= 0xFFFFFFFE;
|
||||
else if (pwr) //Power button still down.
|
||||
res &= ~BTN_POWER;
|
||||
} 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;
|
||||
}
|
||||
|
|
|
@ -25,5 +25,6 @@
|
|||
|
||||
u32 btn_read();
|
||||
u32 btn_wait();
|
||||
u32 btn_wait_timeout(u32 time_ms);
|
||||
|
||||
#endif
|
||||
|
|
61
ipl/di.c
61
ipl/di.c
|
@ -22,6 +22,8 @@
|
|||
#include "i2c.h"
|
||||
#include "pmc.h"
|
||||
#include "max77620.h"
|
||||
#include "gpio.h"
|
||||
#include "pinmux.h"
|
||||
|
||||
#include "di.inl"
|
||||
|
||||
|
@ -56,25 +58,25 @@ void display_init()
|
|||
PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000;
|
||||
|
||||
//Config pins.
|
||||
PINMUX_AUX(0x1D0) &= 0xFFFFFFEF;
|
||||
PINMUX_AUX(0x1D4) &= 0xFFFFFFEF;
|
||||
PINMUX_AUX(0x1FC) &= 0xFFFFFFEF;
|
||||
PINMUX_AUX(0x200) &= 0xFFFFFFEF;
|
||||
PINMUX_AUX(0x204) &= 0xFFFFFFEF;
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= 0xFFFFFFEF;
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= 0xFFFFFFEF;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= 0xFFFFFFEF;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= 0xFFFFFFEF;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= 0xFFFFFFEF;
|
||||
|
||||
GPIO_3(0x00) = (GPIO_3(0x00) & 0xFFFFFFFC) | 0x3;
|
||||
GPIO_3(0x10) = (GPIO_3(0x10) & 0xFFFFFFFC) | 0x3;
|
||||
GPIO_3(0x20) = (GPIO_3(0x20) & 0xFFFFFFFE) | 0x1;
|
||||
|
||||
sleep(10000u);
|
||||
|
||||
GPIO_3(0x20) = (GPIO_3(0x20) & 0xFFFFFFFD) | 0x2;
|
||||
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO); //Backlight +-5V.
|
||||
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE); //Backlight +-5V.
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); //Backlight +5V enable.
|
||||
|
||||
sleep(10000);
|
||||
|
||||
GPIO_6(0x04) = (GPIO_6(0x04) & 0xFFFFFFF8) | 0x7;
|
||||
GPIO_6(0x14) = (GPIO_6(0x14) & 0xFFFFFFF8) | 0x7;
|
||||
GPIO_6(0x24) = (GPIO_6(0x24) & 0xFFFFFFFD) | 0x2;
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); //Backlight -5V enable.
|
||||
|
||||
sleep(10000);
|
||||
|
||||
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.
|
||||
MIPI_CAL(0x60) = 0;
|
||||
|
@ -85,7 +87,7 @@ void display_init()
|
|||
|
||||
sleep(10000);
|
||||
|
||||
GPIO_6(0x24) = (GPIO_6(0x24) & 0xFFFFFFFB) | 0x4;
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH); //Backlight Reset enable.
|
||||
|
||||
sleep(60000);
|
||||
|
||||
|
@ -135,13 +137,16 @@ void display_init()
|
|||
|
||||
void display_backlight(u8 enable)
|
||||
{
|
||||
GPIO_6(0x24) = (GPIO_6(0x24) & 0xFFFFFFFE) | (enable & 1);
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); //Backlight PWM.
|
||||
}
|
||||
|
||||
void display_end()
|
||||
{
|
||||
display_backlight(0);
|
||||
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;
|
||||
|
||||
u32 end = HOST1X(0x30A4) + 5;
|
||||
|
@ -164,17 +169,17 @@ void display_end()
|
|||
|
||||
sleep(50000);
|
||||
|
||||
GPIO_6(0x24) &= 0xFFFFFFFB;
|
||||
//gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable.
|
||||
|
||||
sleep(10000);
|
||||
//sleep(10000);
|
||||
|
||||
GPIO_3(0x20) &= 0xFFFFFFFD;
|
||||
//gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable.
|
||||
|
||||
sleep(10000);
|
||||
//sleep(10000);
|
||||
|
||||
GPIO_3(0x20) = (GPIO_3(0x20) >> 1) << 1;
|
||||
//gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable.
|
||||
|
||||
sleep(10000);
|
||||
//sleep(10000);
|
||||
|
||||
//Disable clocks.
|
||||
CLOCK(0x308) = 0x1010000;
|
||||
|
@ -183,12 +188,12 @@ void display_end()
|
|||
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_POWER_CONTROL)) = 0;
|
||||
DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;*/
|
||||
|
||||
GPIO_6(0x04) &= 0xFFFFFFFE;
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); //Backlight PWM.
|
||||
|
||||
PINMUX_AUX(0x1FC) = (PINMUX_AUX(0x1FC) & 0xFFFFFFEF) | 0x10;
|
||||
PINMUX_AUX(0x1FC) = (PINMUX_AUX(0x1FC) >> 2) << 2 | 1;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFEF) | 0x10;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1;
|
||||
}
|
||||
|
||||
void display_color_screen(u32 color)
|
||||
|
|
16
ipl/gfx.c
16
ipl/gfx.c
|
@ -320,8 +320,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)
|
||||
{
|
||||
int dx = abs(x1-x0), sx = x0 < x1 ? 1 : -1;
|
||||
int dy = abs(y1-y0), sy = y0 < y1 ? 1 : -1;
|
||||
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
||||
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
||||
int err = (dx > dy ? dx : -dy) / 2, e2;
|
||||
|
||||
while (1)
|
||||
|
@ -330,7 +330,15 @@ void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color)
|
|||
if (x0 == x1 && y0 == y1)
|
||||
break;
|
||||
e2 = err;
|
||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
||||
if (e2 < dy) { err += dx; y0 += sy; }
|
||||
if (e2 >-dx)
|
||||
{
|
||||
err -= dy;
|
||||
x0 += sx;
|
||||
}
|
||||
if (e2 < dy)
|
||||
{
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,5 +90,5 @@ void gpio_write(u32 port, u32 pins, int high)
|
|||
|
||||
int gpio_read(u32 port, u32 pins)
|
||||
{
|
||||
return GPIO(_gpio_in[port]) & pins ? 1 : 0;
|
||||
return (GPIO(_gpio_in[port]) & pins) ? 1 : 0;
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@ static void _heap_free(heap_t *heap, u32 addr)
|
|||
while (node)
|
||||
{
|
||||
if (!node->used)
|
||||
{
|
||||
if (node->prev && !node->prev->used)
|
||||
{
|
||||
node->prev->size += node->size + sizeof(hnode_t);
|
||||
|
@ -104,6 +105,7 @@ static void _heap_free(heap_t *heap, u32 addr)
|
|||
if (node->next)
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
@ -129,5 +131,6 @@ void *calloc(u32 num, u32 size)
|
|||
|
||||
void free(void *buf)
|
||||
{
|
||||
if (buf != NULL)
|
||||
_heap_free(&_heap, (u32)buf);
|
||||
}
|
||||
|
|
102
ipl/hos.c
102
ipl/hos.c
|
@ -31,6 +31,7 @@
|
|||
#include "pkg1.h"
|
||||
#include "pkg2.h"
|
||||
#include "ff.h"
|
||||
#include "di.h"
|
||||
|
||||
#include "gfx.h"
|
||||
extern gfx_ctxt_t gfx_ctxt;
|
||||
|
@ -73,9 +74,9 @@ typedef struct _merge_kip_t
|
|||
#define KB_FIRMWARE_VERSION_301 2
|
||||
#define KB_FIRMWARE_VERSION_400 3
|
||||
#define KB_FIRMWARE_VERSION_500 4
|
||||
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_500
|
||||
|
||||
#define NUM_KEYBLOB_KEYS 5
|
||||
static const u8 keyblob_keyseeds[NUM_KEYBLOB_KEYS][0x10] = {
|
||||
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
|
||||
{ 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
|
||||
|
@ -95,24 +96,12 @@ static const u8 console_keyseed[0x10] =
|
|||
static const u8 key8_keyseed[] =
|
||||
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
|
||||
|
||||
static const u8 master_keyseed_4xx[0x10] =
|
||||
static const u8 master_keyseed_4xx_5xx[0x10] =
|
||||
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
|
||||
|
||||
static const u8 console_keyseed_4xx[0x10] =
|
||||
static const u8 console_keyseed_4xx_5xx[0x10] =
|
||||
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
|
||||
|
||||
#define CRC32C_POLY 0x82F63B78
|
||||
u32 crc32c(const u8 *buf, u32 len)
|
||||
{
|
||||
u32 crc = 0xFFFFFFFF;
|
||||
while (len--)
|
||||
{
|
||||
crc ^= *buf++;
|
||||
for (int i = 0; i < 8; i++)
|
||||
crc = crc & 1 ? (crc >> 1) ^ CRC32C_POLY : crc >> 1;
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
static void _se_lock()
|
||||
{
|
||||
|
@ -145,23 +134,26 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
|
|||
{
|
||||
u8 tmp[0x10];
|
||||
|
||||
se_key_acc_ctrl(0x0D, 0x15);
|
||||
se_key_acc_ctrl(0x0E, 0x15);
|
||||
if (kb > KB_FIRMWARE_VERSION_MAX)
|
||||
return 0;
|
||||
|
||||
se_key_acc_ctrl(13, 0x15);
|
||||
se_key_acc_ctrl(14, 0x15);
|
||||
|
||||
//Get TSEC key.
|
||||
if (tsec_query(tmp, 1, tsec_fw) < 0)
|
||||
return 0;
|
||||
|
||||
se_aes_key_set(0x0D, tmp, 0x10);
|
||||
se_aes_key_set(13, tmp, 0x10);
|
||||
|
||||
//Derive keyblob keys from TSEC+SBK.
|
||||
se_aes_crypt_block_ecb(0x0D, 0x00, tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(0x0F, 0x0E, tmp);
|
||||
se_aes_crypt_block_ecb(0xD, 0x00, tmp, keyblob_keyseeds[kb]);
|
||||
se_aes_unwrap_key(0x0D, 0x0E, tmp);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tmp);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]);
|
||||
se_aes_unwrap_key(13, 14, tmp);
|
||||
|
||||
// Clear SBK
|
||||
se_aes_key_clear(0x0E);
|
||||
//Clear SBK.
|
||||
se_aes_key_clear(14);
|
||||
|
||||
//TODO: verify keyblob CMAC.
|
||||
//se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
|
@ -169,45 +161,42 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
|
|||
//if (!memcmp(keyblob, tmp, 0x10))
|
||||
// return 0;
|
||||
|
||||
se_aes_crypt_block_ecb(0x0D, 0, tmp, cmac_keyseed);
|
||||
se_aes_unwrap_key(0x0B, 0x0D, cmac_keyseed);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed);
|
||||
se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
|
||||
//Decrypt keyblob and set keyslots.
|
||||
se_aes_crypt_ctr(0x0D, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(0x0B, keyblob + 0x20 + 0x80, 0x10); // package1 key
|
||||
se_aes_key_set(0x0C, keyblob + 0x20, 0x10);
|
||||
se_aes_key_set(0x0D, keyblob + 0x20, 0x10);
|
||||
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); //Package1 key.
|
||||
se_aes_key_set(12, keyblob + 0x20, 0x10);
|
||||
se_aes_key_set(13, keyblob + 0x20, 0x10);
|
||||
|
||||
se_aes_crypt_block_ecb(0x0C, 0, tmp, master_keyseed_retail);
|
||||
se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail);
|
||||
|
||||
switch (kb)
|
||||
{
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
case KB_FIRMWARE_VERSION_301:
|
||||
se_aes_unwrap_key(0x0D, 0x0F, console_keyseed);
|
||||
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||
se_aes_unwrap_key(13, 15, console_keyseed);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
break;
|
||||
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
se_aes_unwrap_key(0x0D, 0x0F, console_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
|
||||
se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||
se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
break;
|
||||
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
default:
|
||||
se_aes_unwrap_key(0x0A, 0x0F, console_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
|
||||
se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
break;
|
||||
}
|
||||
|
||||
//Package2 key.
|
||||
se_key_acc_ctrl(0x08, 0x15);
|
||||
se_aes_unwrap_key(0x08, 0x0C, key8_keyseed);
|
||||
se_key_acc_ctrl(8, 0x15);
|
||||
se_aes_unwrap_key(8, 12, key8_keyseed);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -385,6 +374,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||
{
|
||||
int bootStateDramPkg2;
|
||||
int bootStatePkg2Continue;
|
||||
int end_di = 0;
|
||||
launch_ctxt_t ctxt;
|
||||
|
||||
memset(&ctxt, 0, sizeof(launch_ctxt_t));
|
||||
|
@ -491,24 +481,25 @@ int hos_launch(ini_sec_t *cfg)
|
|||
|
||||
gfx_printf(&gfx_con, "\n%kBooting...%k\n", 0xFF00FF96, 0xFFCCCCCC);
|
||||
|
||||
se_aes_key_clear(0x8);
|
||||
se_aes_key_clear(0xB);
|
||||
se_aes_key_clear(8);
|
||||
se_aes_key_clear(11);
|
||||
|
||||
switch (ctxt.pkg1_id->kb)
|
||||
{
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
case KB_FIRMWARE_VERSION_301:
|
||||
se_key_acc_ctrl(0xC, 0xFF);
|
||||
se_key_acc_ctrl(0xD, 0xFF);
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(13, 0xFF);
|
||||
bootStateDramPkg2 = 2;
|
||||
bootStatePkg2Continue = 3;
|
||||
end_di = 1;
|
||||
break;
|
||||
default:
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
se_key_acc_ctrl(0xC, 0xFF);
|
||||
se_key_acc_ctrl(0xF, 0xFF);
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(15, 0xFF);
|
||||
bootStateDramPkg2 = 2;
|
||||
bootStatePkg2Continue = 4;
|
||||
break;
|
||||
|
@ -545,8 +536,9 @@ int hos_launch(ini_sec_t *cfg)
|
|||
PMC(0x5BC) = 0xFFFFFFFF;
|
||||
PMC(0x5C0) = 0xFFAAFFFF;*/
|
||||
|
||||
//TODO: Cleanup.
|
||||
//display_end();
|
||||
//Disable display.
|
||||
if (end_di)
|
||||
display_end();
|
||||
|
||||
//Signal to pkg2 ready and continue boot.
|
||||
*mb_in = bootStatePkg2Continue;
|
||||
|
|
48
ipl/ini.c
48
ipl/ini.c
|
@ -91,3 +91,51 @@ int ini_parse(link_t *dst, char *ini_path)
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -35,5 +35,8 @@ typedef struct _ini_sec_t
|
|||
} ini_sec_t;
|
||||
|
||||
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
|
||||
|
|
75
ipl/main.c
75
ipl/main.c
|
@ -870,7 +870,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
|||
// Verify 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);
|
||||
return 0;
|
||||
|
@ -938,7 +938,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
|||
{
|
||||
EPRINTFARGS("\nFailed to read %d blocks @ LBA %08X from eMMC. Aborting..\n",
|
||||
num, lba_curr);
|
||||
EPRINTF("\nPress any key and try again.\n");
|
||||
EPRINTF("\nPress any key and try again...\n");
|
||||
|
||||
free(buf);
|
||||
f_close(&fp);
|
||||
|
@ -949,7 +949,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
|||
if (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);
|
||||
f_close(&fp);
|
||||
|
@ -982,7 +982,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
|||
// Verify last part or single file backup
|
||||
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);
|
||||
return 0;
|
||||
|
@ -1099,7 +1099,7 @@ static void dump_emmc_selected(dumpType_t dumpType)
|
|||
gfx_printf(&gfx_con, "Time taken: %d seconds.\n", (get_tmr() - timer) / 1000000);
|
||||
sdmmc_storage_end(&storage);
|
||||
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:;
|
||||
btn_wait();
|
||||
|
@ -1112,15 +1112,10 @@ void dump_emmc_rawnand() { dump_emmc_selected(DUMP_RAW); }
|
|||
|
||||
void dump_package1()
|
||||
{
|
||||
u8 *pkg1 = (u8 *)malloc(0x40000);
|
||||
u8 *warmboot = (u8 *)malloc(0x40000);
|
||||
u8 *secmon = (u8 *)malloc(0x40000);
|
||||
u8 *loader = (u8 *)malloc(0x40000);
|
||||
|
||||
memset(pkg1, 0, 0x40000);
|
||||
memset(warmboot, 0, 0x40000);
|
||||
memset(secmon, 0, 0x40000);
|
||||
memset(loader, 0, 0x40000);
|
||||
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
|
||||
u8 *warmboot = (u8 *)calloc(1, 0x40000);
|
||||
u8 *secmon = (u8 *)calloc(1, 0x40000);
|
||||
u8 *loader = (u8 *)calloc(1, 0x40000);
|
||||
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
@ -1137,7 +1132,7 @@ void dump_package1()
|
|||
}
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
|
||||
//Read package1.
|
||||
// Read package1.
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
|
||||
|
@ -1151,13 +1146,13 @@ void dump_package1()
|
|||
u8 * keyblob = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||
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);
|
||||
pkg1_decrypt(pkg1_id, pkg1);
|
||||
|
||||
pkg1_unpack(warmboot, secmon, loader, 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, "%kNX Bootloader ofst: %k0x%05X\n\n", 0xFF46EAC7, 0xFFCCCCCC, hdr->ldr_off);
|
||||
|
||||
|
@ -1169,28 +1164,28 @@ void dump_package1()
|
|||
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
|
||||
// Dump package1
|
||||
if (sd_save_to_file(pkg1, 0x40000, "pkg1_decr.bin")) {
|
||||
EPRINTF("\nFailed to create pkg1_decr.bin");
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "\npackage1 dumped to pkg1_decr.bin\n");
|
||||
|
||||
// dump nxbootloader
|
||||
// Dump nxbootloader
|
||||
if (sd_save_to_file(loader, hdr->ldr_size, "nxloader.bin")) {
|
||||
EPRINTF("\nFailed to create nxloader.bin");
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "NX Bootloader dumped to nxloader.bin\n");
|
||||
|
||||
// dump secmon
|
||||
// Dump secmon
|
||||
if (sd_save_to_file(secmon, hdr->sm_size, "secmon.bin")) {
|
||||
EPRINTF("\nFailed to create secmon.bin");
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "Secure Monitor dumped to secmon.bin\n");
|
||||
|
||||
// dump warmboot
|
||||
// Dump warmboot
|
||||
if (sd_save_to_file(warmboot, hdr->wb_size, "warmboot.bin")) {
|
||||
EPRINTF("\nFailed to create warmboot.bin");
|
||||
goto out;
|
||||
|
@ -1199,7 +1194,7 @@ void dump_package1()
|
|||
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
gfx_puts(&gfx_con, "\nDone. Press any key.\n");
|
||||
gfx_puts(&gfx_con, "\nDone. Press any key...\n");
|
||||
|
||||
out:;
|
||||
free(pkg1);
|
||||
|
@ -1212,6 +1207,8 @@ out:;
|
|||
|
||||
void launch_firmware()
|
||||
{
|
||||
u8 max_entries = 16;
|
||||
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
LIST_INIT(ini_sections);
|
||||
|
||||
|
@ -1222,8 +1219,8 @@ void launch_firmware()
|
|||
{
|
||||
if (ini_parse(&ini_sections, "hekate_ipl.ini"))
|
||||
{
|
||||
//Build configuration menu.
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 16);
|
||||
// Build configuration menu.
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * max_entries);
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
u32 i = 1;
|
||||
|
@ -1235,6 +1232,9 @@ void launch_firmware()
|
|||
ments[i].caption = ini_sec->name;
|
||||
ments[i].data = ini_sec;
|
||||
i++;
|
||||
|
||||
if (i > max_entries)
|
||||
break;
|
||||
}
|
||||
if (i > 1)
|
||||
{
|
||||
|
@ -1242,13 +1242,18 @@ void launch_firmware()
|
|||
menu_t menu = {
|
||||
ments, "Launch configurations", 0, 0
|
||||
};
|
||||
cfg_sec = (ini_sec_t *)tui_do_menu(&gfx_con, &menu);
|
||||
cfg_sec = ini_clone_section((ini_sec_t *)tui_do_menu(&gfx_con, &menu));
|
||||
if (!cfg_sec)
|
||||
{
|
||||
free(ments);
|
||||
ini_free(&ini_sections);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
EPRINTF("No launch configurations found.");
|
||||
free(ments);
|
||||
ini_free(&ini_sections);
|
||||
}
|
||||
else
|
||||
EPRINTF("Could not find or open 'hekate_ipl.ini'.\nMake sure it exists in SD Card!.");
|
||||
|
@ -1263,7 +1268,7 @@ void launch_firmware()
|
|||
if (!hos_launch(cfg_sec))
|
||||
EPRINTF("Failed to launch firmware.");
|
||||
|
||||
//TODO: free ini.
|
||||
ini_free_section(cfg_sec);
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
|
@ -1310,19 +1315,19 @@ int fix_attributes(char *path, u32 *total)
|
|||
u32 k = 0;
|
||||
static FILINFO fno;
|
||||
|
||||
/* Open directory */
|
||||
// Open directory
|
||||
res = f_opendir(&dir, path);
|
||||
if (res == FR_OK)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
//Read a directory item.
|
||||
// Read a directory item.
|
||||
res = f_readdir(&dir, &fno);
|
||||
//Break on error or end of dir.
|
||||
// Break on error or end of dir.
|
||||
if (res != FR_OK || fno.fname[0] == 0)
|
||||
break;
|
||||
|
||||
//Set new directory
|
||||
// Set new directory
|
||||
i = strlen(path);
|
||||
memcpy(&path[i], "/", 1);
|
||||
for (k = 0; k < 256; k++)
|
||||
|
@ -1333,23 +1338,23 @@ int fix_attributes(char *path, u32 *total)
|
|||
memcpy(&path[i+1], fno.fname, k + 1);
|
||||
path[i + k + 2] = 0;
|
||||
|
||||
//Check if archive bit is set
|
||||
// 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? */
|
||||
// Is it a directory?
|
||||
if (fno.fattrib & AM_DIR)
|
||||
{
|
||||
//Enter the directory.
|
||||
// Enter the directory.
|
||||
res = fix_attributes(path, total);
|
||||
if (res != FR_OK)
|
||||
break;
|
||||
|
||||
}
|
||||
//Clear file or folder path.
|
||||
// Clear file or folder path.
|
||||
path[i] = 0;
|
||||
}
|
||||
f_closedir(&dir);
|
||||
|
@ -1515,7 +1520,7 @@ void ipl_main()
|
|||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_con_init(&gfx_con, &gfx_ctxt);
|
||||
|
||||
//Enable backlight after initializing gfx
|
||||
// Enable backlight after initializing gfx
|
||||
display_backlight(1);
|
||||
|
||||
while (1)
|
||||
|
|
|
@ -73,8 +73,8 @@ int max77620_regulator_get_status(u32 id)
|
|||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
if (reg->type == REGULATOR_SD)
|
||||
return i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_STATSD) & reg->status_mask ? 0 : 1;
|
||||
return i2c_recv_byte(I2C_5, 0x3C, reg->cfg_addr) & 8 ? 1 : 0;
|
||||
return (i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1;
|
||||
return (i2c_recv_byte(I2C_5, 0x3C, reg->cfg_addr) & 8) ? 1 : 0;
|
||||
}
|
||||
|
||||
int max77620_regulator_config_fps(u32 id)
|
||||
|
|
|
@ -41,6 +41,11 @@
|
|||
#define PINMUX_AUX_DMIC3_CLK 0xB4
|
||||
#define PINMUX_AUX_UART2_TX 0xF4
|
||||
#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_PH6 0x250
|
||||
#define PINMUX_AUX_GPIO_PZ1 0x280
|
||||
|
|
10
ipl/pkg1.c
10
ipl/pkg1.c
|
@ -16,19 +16,13 @@
|
|||
|
||||
#include <string.h>
|
||||
#include "pkg1.h"
|
||||
#include "arm64.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 0x4002B020
|
||||
|
||||
PATCHSET_DEF(_secmon_1_patchset,
|
||||
//Patch the relocator to be able to run from SM_100_ADR.
|
||||
{ 0x1E0, _ADRP(0, 0x7C013000 - (SM_100_ADR - 0x40)) },
|
||||
{ 0x1E0, _ADRP(0, 0x7C013000 - _PAGEOFF(SM_100_ADR)) },
|
||||
//Patch package2 decryption and signature/hash checks.
|
||||
{ 0x9F0 + 0xADC, _NOP() }, //Header signature.
|
||||
{ 0x9F0 + 0xB8C, _NOP() }, //Version.
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include "pkg2.h"
|
||||
#include "arm64.h"
|
||||
#include "heap.h"
|
||||
#include "se.h"
|
||||
|
||||
|
@ -25,9 +26,6 @@ extern gfx_con_t gfx_con;
|
|||
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/
|
||||
#define DPRINTF(...)
|
||||
|
||||
#define _MOVZX(r, i, s) 0xD2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F)
|
||||
#define _NOP() 0xD503201F
|
||||
|
||||
// Include kernel patches here, so we can utilize pkg1 id
|
||||
PATCHSET_DEF(_kernel_1_patchset,
|
||||
{ 0x3764C, _NOP() }, // Disable SVC verifications
|
||||
|
|
|
@ -849,7 +849,7 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
|||
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
|
||||
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))
|
||||
{
|
||||
case 0:
|
||||
|
|
11
ipl/tui.c
11
ipl/tui.c
|
@ -40,8 +40,7 @@ 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)
|
||||
{
|
||||
int idx = 0, cnt = 0;
|
||||
int prev_idx = 0;
|
||||
int idx = 0, prev_idx = 0, cnt = 0x7FFFFFFF;
|
||||
|
||||
gfx_clear_grey(con->gfx_ctxt, 0x1B);
|
||||
|
||||
|
@ -51,7 +50,7 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
|
|||
gfx_con_setpos(con, menu->x, menu->y);
|
||||
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 ||
|
||||
menu->ents[idx].type == MENT_CHGLINE)
|
||||
{
|
||||
|
@ -76,16 +75,16 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
|
|||
}
|
||||
prev_idx = idx;
|
||||
|
||||
// Draw the menu
|
||||
//Draw the menu.
|
||||
for (cnt = 0; menu->ents[cnt].type != MENT_END; cnt++)
|
||||
{
|
||||
if (cnt == idx)
|
||||
gfx_con_setcol(con, 0xFF1B1B1B, 1, 0xFFCCCCCC);
|
||||
else
|
||||
gfx_con_setcol(con, 0xFFCCCCCC, 1, 0xFF1B1B1B);
|
||||
if (cnt != idx && menu->ents[cnt].type == MENT_CAPTION)
|
||||
if (menu->ents[cnt].type == MENT_CAPTION)
|
||||
gfx_printf(con, "%k %s", menu->ents[cnt].color, menu->ents[cnt].caption);
|
||||
else
|
||||
else if (menu->ents[cnt].type != MENT_CHGLINE)
|
||||
gfx_printf(con, " %s", menu->ents[cnt].caption);
|
||||
if(menu->ents[cnt].type == MENT_MENU)
|
||||
gfx_printf(con, "%k...", 0xFFEE9900);
|
||||
|
|
13
ipl/util.c
13
ipl/util.c
|
@ -35,3 +35,16 @@ void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -28,5 +28,6 @@ typedef struct _cfg_op_t
|
|||
u32 get_tmr();
|
||||
void sleep(u32 ticks);
|
||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
||||
u32 crc32c(const void *buf, u32 len);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue