Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
678e8d34e3 | ||
|
|
07d1982abf | ||
|
|
fd05f83636 | ||
|
|
94e119fb51 | ||
|
|
c2ff4bf623 | ||
|
|
faf5651607 | ||
|
|
978e8344cf | ||
|
|
160d6eacc0 | ||
|
|
075d8e6393 | ||
|
|
28008ac7ac | ||
|
|
345d36287e | ||
|
|
edff6c551d | ||
|
|
d42a94f148 | ||
|
|
c01b8aa89c | ||
|
|
4958bd6a52 | ||
|
|
46038032a4 | ||
|
|
f66ddca100 | ||
|
|
6981c59de3 | ||
|
|
f21f13b15d | ||
|
|
ef5a01433d | ||
|
|
0e12d8545b | ||
|
|
9dbf745649 | ||
|
|
e8f73a42b8 | ||
|
|
dbe431095a | ||
|
|
513f77a2ad | ||
|
|
e8cf85bd65 | ||
|
|
be23d1fa15 | ||
|
|
4e7e5081a7 | ||
|
|
fff750e609 | ||
|
|
38ce46a158 | ||
|
|
7a27a7b3b5 |
@@ -88,7 +88,7 @@ You can find a template [Here](./res/hekate_ipl_template.ini)
|
||||
| kip1patch=patchname | Enables a kip1 patch. Specify with multiple lines and/or as CSV. If not found, an error will show up |
|
||||
| fullsvcperm=1 | Disables SVC verification (full services permission) |
|
||||
| debugmode=1 | Enables Debug mode. Obsolete when used with exosphere as secmon. |
|
||||
| atmosphere=1 | Enables Atmosphère patching. |
|
||||
| atmosphere=1 | Enables Atmosphère patching. Not needed when `fss0` is used. |
|
||||
| emupath={SD folder} | Forces emuMMC to use the selected one. (=emuMMC/RAW1, =emuMMC/SD00, etc). emuMMC must be created by hekate because it uses the raw_based/file_based files. |
|
||||
| emummcforce=1 | Forces the use of emuMMC. If emummc.ini is disabled or not found, then it causes an error. |
|
||||
| emummc_force_disable=1 | Disables emuMMC, if it's enabled. |
|
||||
@@ -139,9 +139,9 @@ If the main .ini is not found, it is created on the first hekate boot.
|
||||
|
||||
```
|
||||
hekate (c) 2018, naehrwert, st4rk.
|
||||
(c) 2018-2020, CTCaer.
|
||||
(c) 2018-2021, CTCaer.
|
||||
|
||||
Nyx GUI (c) 2019-2020, CTCaer.
|
||||
Nyx GUI (c) 2019-2021, CTCaer.
|
||||
|
||||
Thanks to: derrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8.
|
||||
Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# IPL Version.
|
||||
BLVERSION_MAJOR := 5
|
||||
BLVERSION_MINOR := 5
|
||||
BLVERSION_HOTFX := 4
|
||||
BLVERSION_HOTFX := 5
|
||||
BLVERSION_RSVD := 0
|
||||
|
||||
# Nyx Version.
|
||||
NYXVERSION_MAJOR := 1
|
||||
NYXVERSION_MINOR := 0
|
||||
NYXVERSION_HOTFX := 0
|
||||
NYXVERSION_HOTFX := 2
|
||||
NYXVERSION_RSVD := 0
|
||||
|
||||
@@ -507,6 +507,11 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
|
||||
}
|
||||
|
||||
u32 display_get_backlight_brightness()
|
||||
{
|
||||
return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
static void _display_panel_and_hw_end(bool no_panel_deinit)
|
||||
{
|
||||
if (no_panel_deinit)
|
||||
|
||||
@@ -706,6 +706,7 @@ void display_color_screen(u32 color);
|
||||
/*! Switches screen backlight ON/OFF. */
|
||||
void display_backlight(bool enable);
|
||||
void display_backlight_brightness(u32 brightness, u32 step_delay);
|
||||
u32 display_get_backlight_brightness();
|
||||
|
||||
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
|
||||
u32 *display_init_framebuffer_pitch();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "elfload/elfload.h"
|
||||
#include <module.h>
|
||||
#include <mem/heap.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <storage/nx_sd.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
@@ -43,6 +44,10 @@ static void _ianos_call_ep(moduleEntrypoint_t entrypoint, void *moduleConfig)
|
||||
bdkParameters->memset = (memset_t)&memset;
|
||||
bdkParameters->sharedHeap = &_heap;
|
||||
|
||||
// Extra functions.
|
||||
bdkParameters->extension_magic = IANOS_EXT0;
|
||||
bdkParameters->reg_voltage_set = (reg_voltage_set_t)&max7762x_regulator_set_voltage;
|
||||
|
||||
entrypoint(moduleConfig, bdkParameters);
|
||||
}
|
||||
|
||||
|
||||
@@ -463,7 +463,7 @@ static void jc_rcv_pkt(joycon_ctxt_t *jc)
|
||||
|
||||
// Check if device stopped sending data.
|
||||
u32 uart_irq = uart_get_IIR(jc->uart);
|
||||
if ((uart_irq & 0x8) != 0x8)
|
||||
if (uart_irq != UART_IIR_REDI)
|
||||
return;
|
||||
|
||||
u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100);
|
||||
@@ -694,9 +694,15 @@ retry:
|
||||
|
||||
void jc_deinit()
|
||||
{
|
||||
// Disable power.
|
||||
jc_power_supply(UART_B, false);
|
||||
jc_power_supply(UART_C, false);
|
||||
|
||||
// Turn off Joy-Con detect.
|
||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
|
||||
// Send sleep command.
|
||||
u8 data = HCI_STATE_SLEEP;
|
||||
|
||||
if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
|
||||
@@ -709,9 +715,6 @@ void jc_deinit()
|
||||
jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||
jc_rcv_pkt(&jc_l);
|
||||
}
|
||||
|
||||
jc_power_supply(UART_B, false);
|
||||
jc_power_supply(UART_C, false);
|
||||
}
|
||||
|
||||
static void jc_init_conn(joycon_ctxt_t *jc)
|
||||
|
||||
@@ -206,6 +206,7 @@ touch_panel_info_t *touch_get_panel_vendor()
|
||||
{
|
||||
u8 buf[5] = {0};
|
||||
u8 cmd = STMFTS_VENDOR_GPIO_STATE;
|
||||
static touch_panel_info_t panel_info = { -2, 0, 0, 0, ""};
|
||||
|
||||
if (touch_command(STMFTS_VENDOR, &cmd, 1))
|
||||
return NULL;
|
||||
@@ -220,13 +221,20 @@ touch_panel_info_t *touch_get_panel_vendor()
|
||||
return panel;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
// Touch panel not found, return current gpios.
|
||||
panel_info.gpio0 = buf[0];
|
||||
panel_info.gpio1 = buf[1];
|
||||
panel_info.gpio2 = buf[2];
|
||||
|
||||
return &panel_info;
|
||||
}
|
||||
|
||||
int touch_get_fw_info(touch_fw_info_t *fw)
|
||||
{
|
||||
u8 buf[8] = {0};
|
||||
|
||||
memset(fw, 0, sizeof(touch_fw_info_t));
|
||||
|
||||
// Get fw address info.
|
||||
u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0x60 };
|
||||
int res = touch_read_reg(cmd, 3, buf, 3);
|
||||
@@ -318,7 +326,7 @@ int touch_get_fb_info(u8 *buf)
|
||||
int res = 0;
|
||||
|
||||
|
||||
for (u32 i = 0; i < 0x10000; i+=4)
|
||||
for (u32 i = 0; i < 0x10000; i += 4)
|
||||
{
|
||||
if (!res)
|
||||
{
|
||||
@@ -392,11 +400,11 @@ static int touch_init()
|
||||
|
||||
int touch_power_on()
|
||||
{
|
||||
// Enable LDO6 for touchscreen VDD/AVDD supply.
|
||||
// Enable LDO6 for touchscreen AVDD supply.
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO6, true);
|
||||
|
||||
// Configure touchscreen GPIO.
|
||||
// Configure touchscreen VDD GPIO.
|
||||
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
|
||||
gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE);
|
||||
@@ -410,7 +418,7 @@ int touch_power_on()
|
||||
// Configure Touscreen and GCAsic shared GPIO.
|
||||
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2;
|
||||
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2;
|
||||
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO);
|
||||
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect.
|
||||
|
||||
// Initialize I2C3.
|
||||
pinmux_config_i2c(I2C_3);
|
||||
|
||||
@@ -839,10 +839,12 @@ int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst
|
||||
int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
|
||||
{
|
||||
int result;
|
||||
LZ4_stream_t ctx;
|
||||
LZ4_stream_t* const ctxPtr = &ctx;
|
||||
LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
|
||||
LZ4_stream_t* const ctxPtr = ctx;
|
||||
result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
|
||||
|
||||
FREEMEM(ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -857,13 +859,18 @@ int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxO
|
||||
/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
|
||||
int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
|
||||
{
|
||||
LZ4_stream_t ctx;
|
||||
LZ4_resetStream(&ctx);
|
||||
int result;
|
||||
LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
|
||||
LZ4_resetStream(ctx);
|
||||
|
||||
if (inputSize < LZ4_64Klimit)
|
||||
return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
|
||||
result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
|
||||
else
|
||||
return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
|
||||
result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
|
||||
|
||||
FREEMEM(ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1045,11 +1052,13 @@ static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src,
|
||||
|
||||
int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
|
||||
{
|
||||
LZ4_stream_t ctxBody;
|
||||
LZ4_stream_t* ctx = &ctxBody;
|
||||
LZ4_stream_t* ctxBody = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));;
|
||||
LZ4_stream_t* ctx = ctxBody;
|
||||
|
||||
int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
|
||||
|
||||
FREEMEM(ctxBody);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -3323,11 +3323,13 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
#if FF_SIMPLE_GPT
|
||||
if (fmt >= 2) {
|
||||
/* If GPT Check the first partition */
|
||||
gpt_t gpt;
|
||||
if (disk_read(fs->pdrv, (BYTE *)&gpt, 1, sizeof(gpt_t) / SS(fs))) return FR_DISK_ERR;
|
||||
if (!mem_cmp(&gpt.header.signature, "EFI PART", 8)) {
|
||||
gpt_header_t *gpt_header = (gpt_header_t *)fs->win;
|
||||
if (move_window(fs, 1) != FR_OK) return FR_DISK_ERR;
|
||||
if (!mem_cmp(&gpt_header->signature, "EFI PART", 8)) {
|
||||
if (move_window(fs, gpt_header->part_ent_lba) != FR_OK) return FR_DISK_ERR;
|
||||
gpt_entry_t *gpt_entry = (gpt_entry_t *)fs->win;
|
||||
fs->part_type = 1;
|
||||
bsect = gpt.entries[0].lba_start;
|
||||
bsect = gpt_entry->lba_start;
|
||||
fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,21 +104,21 @@ u32 minerva_init()
|
||||
}
|
||||
|
||||
mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz;
|
||||
mtc_cfg->rate_to = 204000;
|
||||
mtc_cfg->rate_to = FREQ_204;
|
||||
mtc_cfg->train_mode = OP_TRAIN;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
mtc_cfg->rate_to = 800000;
|
||||
mtc_cfg->rate_to = FREQ_800;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
mtc_cfg->rate_to = 1600000;
|
||||
mtc_cfg->rate_to = FREQ_1600;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
|
||||
// FSP WAR.
|
||||
mtc_cfg->train_mode = OP_SWITCH;
|
||||
mtc_cfg->rate_to = 800000;
|
||||
mtc_cfg->rate_to = FREQ_800;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
|
||||
// Switch to max.
|
||||
mtc_cfg->rate_to = 1600000;
|
||||
mtc_cfg->rate_to = FREQ_1600;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
|
||||
return 0;
|
||||
@@ -139,6 +139,23 @@ void minerva_change_freq(minerva_freq_t freq)
|
||||
}
|
||||
}
|
||||
|
||||
void minerva_prep_boot_freq()
|
||||
{
|
||||
if (!minerva_cfg)
|
||||
return;
|
||||
|
||||
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
|
||||
|
||||
// Check if there's RAM OC. If not exit.
|
||||
if (mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)
|
||||
return;
|
||||
|
||||
// FSP WAR.
|
||||
minerva_change_freq(FREQ_204);
|
||||
// Scale down to 800 MHz boot freq.
|
||||
minerva_change_freq(FREQ_800);
|
||||
}
|
||||
|
||||
void minerva_periodic_training()
|
||||
{
|
||||
if (!minerva_cfg)
|
||||
|
||||
@@ -60,6 +60,7 @@ typedef enum
|
||||
extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
|
||||
u32 minerva_init();
|
||||
void minerva_change_freq(minerva_freq_t freq);
|
||||
void minerva_prep_boot_freq();
|
||||
void minerva_periodic_training();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
#include <stddef.h>
|
||||
#include <mem/heap.h>
|
||||
|
||||
#define IANOS_EXT0 0x304E4149
|
||||
|
||||
// Module Callback
|
||||
typedef void (*cbMainModule_t)(const char *s);
|
||||
typedef void (*memcpy_t)(void *, void *, size_t);
|
||||
typedef void (*memset_t)(void *, int, size_t);
|
||||
typedef int (*reg_voltage_set_t)(u32, u32);
|
||||
|
||||
typedef struct _bdkParams_t
|
||||
{
|
||||
@@ -33,6 +36,8 @@ typedef struct _bdkParams_t
|
||||
heap_t *sharedHeap;
|
||||
memcpy_t memcpy;
|
||||
memset_t memset;
|
||||
u32 extension_magic;
|
||||
reg_voltage_set_t reg_voltage_set;
|
||||
} *bdkParams_t;
|
||||
|
||||
// Module Entrypoint
|
||||
|
||||
@@ -75,7 +75,7 @@ typedef struct _max77620_regulator_t
|
||||
|
||||
static const max77620_regulator_t _pmic_regulators[] = {
|
||||
{ "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
|
||||
{ "sd1", 12500, 600000, 1125000, 1125000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
|
||||
{ "sd1", 12500, 600000, 1125000, 1250000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
|
||||
{ "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
|
||||
{ "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
|
||||
{ "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
|
||||
@@ -328,6 +328,7 @@ void max77620_config_default()
|
||||
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0);
|
||||
}
|
||||
|
||||
// Stock HOS: disabled.
|
||||
void max77620_low_battery_monitor_config(bool enable)
|
||||
{
|
||||
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1,
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
|
||||
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
|
||||
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
|
||||
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 |
|
||||
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | 0.85V (AO, pcv)
|
||||
* ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
|
||||
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V
|
||||
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 |
|
||||
* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 |
|
||||
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V (pcv)
|
||||
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
|
||||
* ldo8 | XUSB, DP, MCU | 50000 | 800000 | 1050000 | 2800000 | 1.05V/2.8V (pcv)
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -135,10 +135,10 @@
|
||||
#define MAX77621_CTRL_HOS_CFG 0
|
||||
#define MAX77621_CTRL_POR_CFG 1
|
||||
|
||||
int max77620_regulator_get_status(u32 id);
|
||||
int max77620_regulator_config_fps(u32 id);
|
||||
int max7762x_regulator_set_voltage(u32 id, u32 mv);
|
||||
int max7762x_regulator_enable(u32 id, bool enable);
|
||||
int max77620_regulator_get_status(u32 id);
|
||||
int max77620_regulator_config_fps(u32 id);
|
||||
int max7762x_regulator_set_voltage(u32 id, u32 mv);
|
||||
int max7762x_regulator_enable(u32 id, bool enable);
|
||||
void max77620_config_gpio(u32 id, bool enable);
|
||||
void max77620_config_default();
|
||||
void max77620_low_battery_monitor_config(bool enable);
|
||||
|
||||
@@ -81,7 +81,13 @@ bool regulator_5v_get_dev_enabled(u8 dev)
|
||||
void regulator_5v_batt_src_enable(bool enable)
|
||||
{
|
||||
if (enable && !batt_src)
|
||||
{
|
||||
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
|
||||
batt_src = true;
|
||||
}
|
||||
else if (!enable && batt_src)
|
||||
{
|
||||
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW);
|
||||
batt_src = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ static void _config_oscillators()
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
|
||||
}
|
||||
|
||||
// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula.
|
||||
static void _config_gpios(bool nx_hoag)
|
||||
{
|
||||
// Clamp inputs when tristated.
|
||||
@@ -420,7 +421,7 @@ void hw_init()
|
||||
bpmp_mmu_enable();
|
||||
}
|
||||
|
||||
void hw_reinit_workaround(bool coreboot, u32 magic)
|
||||
void hw_reinit_workaround(bool coreboot, u32 bl_magic)
|
||||
{
|
||||
// Disable BPMP max clock.
|
||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
@@ -462,11 +463,22 @@ void hw_reinit_workaround(bool coreboot, u32 magic)
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
|
||||
}
|
||||
|
||||
// Power off display.
|
||||
display_end();
|
||||
// Seamless display or display power off.
|
||||
switch (bl_magic)
|
||||
{
|
||||
case BL_MAGIC_CRBOOT_SLD:;
|
||||
// Set pwm to 0%, switch to gpio mode and restore pwm duty.
|
||||
u32 brightness = display_get_backlight_brightness();
|
||||
display_backlight_brightness(0, 1000);
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO);
|
||||
display_backlight_brightness(brightness, 0);
|
||||
break;
|
||||
default:
|
||||
display_end();
|
||||
}
|
||||
|
||||
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
|
||||
if (magic == 0xBAADF00D)
|
||||
if (bl_magic == BL_MAGIC_BROKEN_HWI)
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
|
||||
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
|
||||
#include <utils/types.h>
|
||||
|
||||
#define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0.
|
||||
#define BL_MAGIC_BROKEN_HWI 0xBAADF00D // Broken hwinit.
|
||||
|
||||
void hw_init();
|
||||
void hw_reinit_workaround(bool coreboot, u32 magic);
|
||||
u32 hw_get_chip_id();
|
||||
|
||||
@@ -122,7 +122,12 @@ u32 uart_get_IIR(u32 idx)
|
||||
{
|
||||
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
|
||||
|
||||
return uart->UART_IIR_FCR;
|
||||
u32 iir = uart->UART_IIR_FCR & UART_IIR_INT_MASK;
|
||||
|
||||
if (iir & UART_IIR_NO_INT)
|
||||
return 0;
|
||||
else
|
||||
return ((iir >> 1) + 1); // Return encoded interrupt.
|
||||
}
|
||||
|
||||
void uart_set_IIR(u32 idx)
|
||||
|
||||
@@ -54,6 +54,17 @@
|
||||
#define UART_IIR_FCR_RX_CLR 0x2
|
||||
#define UART_IIR_FCR_EN_FIFO 0x1
|
||||
|
||||
#define UART_IIR_NO_INT BIT(0)
|
||||
#define UART_IIR_INT_MASK 0xF
|
||||
/* Custom returned interrupt results. Actual interrupts are -1 */
|
||||
#define UART_IIR_NOI 0 // No interrupt.
|
||||
#define UART_IIR_MSI 1 // Modem status interrupt.
|
||||
#define UART_IIR_THRI 2 // Transmitter holding register empty.
|
||||
#define UART_IIR_RDI 3 // Receiver data interrupt.
|
||||
#define UART_IIR_ERROR 4 // Overrun Error, Parity Error, Framing Error, Break.
|
||||
#define UART_IIR_REDI 5 // Receiver end of data interrupt.
|
||||
#define UART_IIR_RDTI 7 // Receiver data timeout interrupt.
|
||||
|
||||
#define UART_MCR_RTS 0x2
|
||||
#define UART_MCR_DTR 0x1
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
void set_fan_duty(u32 duty)
|
||||
{
|
||||
static bool fan_init = false;
|
||||
static u16 curr_duty = -1;
|
||||
static u16 curr_duty = -1;
|
||||
|
||||
if (curr_duty == duty)
|
||||
return;
|
||||
@@ -79,15 +79,14 @@ void get_fan_speed(u32 *duty, u32 *rpm)
|
||||
{
|
||||
if (rpm)
|
||||
{
|
||||
u32 irq_count = 1;
|
||||
u32 irq_count = 0;
|
||||
bool should_read = true;
|
||||
bool irq_val = 0;
|
||||
|
||||
// Poll irqs for 2 seconds.
|
||||
int timer = get_tmr_us() + 1000000;
|
||||
while (timer - get_tmr_us())
|
||||
// Poll irqs for 2 seconds. (5 seconds for accurate count).
|
||||
int timer = get_tmr_us() + 2000000;
|
||||
while ((timer - get_tmr_us()) > 0)
|
||||
{
|
||||
irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7);
|
||||
bool irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7);
|
||||
if (irq_val && should_read)
|
||||
{
|
||||
irq_count++;
|
||||
@@ -97,8 +96,11 @@ void get_fan_speed(u32 *duty, u32 *rpm)
|
||||
should_read = true;
|
||||
}
|
||||
|
||||
// Halve the irq count.
|
||||
irq_count /= 2;
|
||||
|
||||
// Calculate rpm based on triggered interrupts.
|
||||
*rpm = 60000000 / ((1000000 * 2) / irq_count);
|
||||
*rpm = irq_count * (60 / 2);
|
||||
}
|
||||
|
||||
if (duty)
|
||||
|
||||
@@ -1837,6 +1837,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
||||
// Initialize sdmmc.
|
||||
if (usbs->type == MMC_SD)
|
||||
{
|
||||
sd_end();
|
||||
sd_mount();
|
||||
sd_unmount();
|
||||
ums.lun.sdmmc = &sd_sdmmc;
|
||||
|
||||
@@ -21,16 +21,16 @@
|
||||
#include <mem/heap.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
#define MAX_ENTRIES 64
|
||||
|
||||
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
|
||||
{
|
||||
u8 max_entries = 61;
|
||||
|
||||
int res = 0;
|
||||
u32 i = 0, j = 0, k = 0;
|
||||
DIR dir;
|
||||
FILINFO fno;
|
||||
|
||||
char *dir_entries = (char *)calloc(max_entries, 256);
|
||||
char *dir_entries = (char *)calloc(MAX_ENTRIES, 256);
|
||||
char *temp = (char *)calloc(1, 256);
|
||||
|
||||
if (!pattern && !f_opendir(&dir, directory))
|
||||
@@ -49,7 +49,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
|
||||
{
|
||||
strcpy(dir_entries + (k * 256), fno.fname);
|
||||
k++;
|
||||
if (k > (max_entries - 1))
|
||||
if (k > (MAX_ENTRIES - 1))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
|
||||
{
|
||||
strcpy(dir_entries + (k * 256), fno.fname);
|
||||
k++;
|
||||
if (k > (max_entries - 1))
|
||||
if (k > (MAX_ENTRIES - 1))
|
||||
break;
|
||||
}
|
||||
res = f_findnext(&dir, &fno);
|
||||
|
||||
@@ -66,14 +66,14 @@ ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type
|
||||
|
||||
int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
{
|
||||
FIL fp;
|
||||
u32 lblen;
|
||||
u32 pathlen = strlen(ini_path);
|
||||
u32 k = 0;
|
||||
char lbuf[512];
|
||||
char *filelist = NULL;
|
||||
FIL fp;
|
||||
ini_sec_t *csec = NULL;
|
||||
|
||||
char *lbuf = NULL;
|
||||
char *filelist = NULL;
|
||||
char *filename = (char *)malloc(256);
|
||||
|
||||
strcpy(filename, ini_path);
|
||||
@@ -114,6 +114,8 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
return 0;
|
||||
}
|
||||
|
||||
lbuf = malloc(512);
|
||||
|
||||
do
|
||||
{
|
||||
// Fetch one line.
|
||||
@@ -168,6 +170,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
}
|
||||
} while (is_dir);
|
||||
|
||||
free(lbuf);
|
||||
free(filename);
|
||||
free(filelist);
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#ifndef _TYPES_H_
|
||||
#define _TYPES_H_
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define NULL ((void *)0)
|
||||
|
||||
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||
@@ -116,6 +118,8 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t
|
||||
};
|
||||
} boot_cfg_t;
|
||||
|
||||
static_assert(sizeof(boot_cfg_t) == 0x84, "Boot CFG size is wrong!");
|
||||
|
||||
typedef struct __attribute__((__packed__)) _ipl_ver_meta_t
|
||||
{
|
||||
u32 magic;
|
||||
|
||||
@@ -81,15 +81,16 @@ typedef struct _fss_content_t
|
||||
char name[0x10];
|
||||
} fss_content_t;
|
||||
|
||||
static void _update_r2p(const char *path)
|
||||
static void _update_r2p(launch_ctxt_t *ctxt, const char *path)
|
||||
{
|
||||
char *r2p_path = malloc(256);
|
||||
char *r2p_path = malloc(512);
|
||||
u32 path_len = strlen(path);
|
||||
|
||||
strcpy(r2p_path, path);
|
||||
|
||||
while(path_len)
|
||||
{
|
||||
if ((r2p_path[path_len - 1] == '/') || (r2p_path[path_len - 1] == 0x5C))
|
||||
if ((r2p_path[path_len - 1] == '/') || (r2p_path[path_len - 1] == '\\'))
|
||||
{
|
||||
r2p_path[path_len] = 0;
|
||||
strcat(r2p_path, "reboot_payload.bin");
|
||||
@@ -98,6 +99,15 @@ static void _update_r2p(const char *path)
|
||||
is_ipl_updated(r2p_payload, r2p_path, h_cfg.updater2p ? true : false);
|
||||
|
||||
free(r2p_payload);
|
||||
|
||||
// Save fss0 parrent path.
|
||||
if (ctxt)
|
||||
{
|
||||
r2p_path[path_len] = 0;
|
||||
ctxt->fss0_main_path = r2p_path;
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
path_len--;
|
||||
@@ -264,7 +274,7 @@ out:
|
||||
gfx_printf("Done!\n");
|
||||
f_close(&fp);
|
||||
|
||||
_update_r2p(path);
|
||||
_update_r2p(ctxt, path);
|
||||
|
||||
return (!sept_ctxt ? 1 : sept_used);
|
||||
}
|
||||
|
||||
@@ -684,7 +684,7 @@ static bool _get_fs_exfat_compatible(link_t *info, bool *fs_is_510)
|
||||
|
||||
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
|
||||
{
|
||||
if (strncmp((const char*)ki->kip1->name, "FS", 2))
|
||||
if (strncmp((const char*)ki->kip1->name, "FS", sizeof(ki->kip1->name)))
|
||||
continue;
|
||||
|
||||
if (!se_calc_sha256_oneshot(sha_buf, ki->kip1, ki->size))
|
||||
@@ -798,12 +798,14 @@ int hos_launch(ini_sec_t *cfg)
|
||||
(!(fuses & ~0xF) && (ctxt.pkg1_id->fuses >= 5)) || // LAFW v2, 4.0.0+
|
||||
(!(fuses & ~0x3FF) && (ctxt.pkg1_id->fuses >= 11)) || // LAFW v3, 9.0.0+
|
||||
(!(fuses & ~0x1FFF) && (ctxt.pkg1_id->fuses >= 14)) // LAFW v4, 11.0.0+
|
||||
// Detection broken! Use kip1patch=nogc // LAFW v5, 12.0.0+
|
||||
)
|
||||
)
|
||||
|| ((emummc_enabled) &&
|
||||
(
|
||||
((fuses & 0x400) && (ctxt.pkg1_id->fuses <= 10)) || // HOS 9.0.0+ fuses burnt.
|
||||
((fuses & 0x400) && (ctxt.pkg1_id->fuses <= 10)) || // HOS 9.0.0+ fuses burnt.
|
||||
((fuses & 0x2000) && (ctxt.pkg1_id->fuses <= 13)) // HOS 11.0.0+ fuses burnt.
|
||||
// Detection broken! Use kip1patch=nogc // HOS 12.0.0+
|
||||
)
|
||||
))
|
||||
config_kip1patch(&ctxt, "nogc");
|
||||
@@ -1140,6 +1142,10 @@ int hos_launch(ini_sec_t *cfg)
|
||||
bpmp_mmu_disable();
|
||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
|
||||
// Scale down RAM OC if enabled.
|
||||
if (ctxt.stock)
|
||||
minerva_prep_boot_freq();
|
||||
|
||||
// emuMMC: Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
|
||||
sdmmc_storage_init_wait_sd();
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ typedef struct _exo_ctxt_t
|
||||
bool fs_is_510;
|
||||
bool no_user_exceptions;
|
||||
bool user_pmu;
|
||||
bool *usb3_force;
|
||||
bool *cal0_blank;
|
||||
bool *cal0_allow_writes_sys;
|
||||
} exo_ctxt_t;
|
||||
@@ -107,14 +108,16 @@ typedef struct _launch_ctxt_t
|
||||
link_t kip1_list;
|
||||
char* kip1_patches;
|
||||
|
||||
u32 fss0_hosver;
|
||||
bool svcperm;
|
||||
bool debugmode;
|
||||
bool stock;
|
||||
bool atmosphere;
|
||||
bool fss0_experimental;
|
||||
bool emummc_forced;
|
||||
|
||||
char *fss0_main_path;
|
||||
u32 fss0_hosver;
|
||||
bool fss0_experimental;
|
||||
bool atmosphere;
|
||||
|
||||
exo_ctxt_t exo_ctx;
|
||||
|
||||
ini_sec_t *cfg;
|
||||
|
||||
@@ -220,6 +220,19 @@ static int _config_exo_user_pmu_access(launch_ctxt_t *ctxt, const char *value)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_exo_usb3_force(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
ctxt->exo_ctx.usb3_force = calloc(sizeof(bool), 1);
|
||||
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled USB 3.0\n");
|
||||
*ctxt->exo_ctx.usb3_force = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
@@ -291,6 +304,7 @@ static const cfg_handler_t _config_handlers[] = {
|
||||
{ "emummcforce", _config_emummc_forced },
|
||||
{ "nouserexceptions", _config_dis_exo_user_exceptions },
|
||||
{ "userpmu", _config_exo_user_pmu_access },
|
||||
{ "usb3force", _config_exo_usb3_force },
|
||||
{ "cal0blank", _config_exo_cal0_blanking },
|
||||
{ "cal0writesys", _config_exo_cal0_writes_enable },
|
||||
{ NULL, NULL },
|
||||
|
||||
@@ -170,7 +170,8 @@ static const pkg1_id_t _pkg1_ids[] = {
|
||||
{ "20190809135709", 9, 11, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.0.0 - 9.0.1.
|
||||
{ "20191021113848", 10, 12, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.1.0 - 9.2.0.
|
||||
{ "20200303104606", 10, 13, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 10.0.0 - 10.2.0.
|
||||
{ "20201030110855", 10, 14, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 11.0.0+
|
||||
{ "20201030110855", 10, 14, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 11.0.0 - 11.0.1
|
||||
{ "20210129111626", 10, 14, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 12.0.0+
|
||||
{ NULL } // End.
|
||||
};
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ u32 pkg2_newkern_ini1_end;
|
||||
#define FREE_CODE_OFF_1ST_900 0x65780
|
||||
#define FREE_CODE_OFF_1ST_1000 0x67790
|
||||
#define FREE_CODE_OFF_1ST_1100 0x49EE8
|
||||
#define FREE_CODE_OFF_1ST_1200 0x48810
|
||||
|
||||
#define ID_SND_OFF_100 0x23CC0
|
||||
#define ID_SND_OFF_200 0x3F134
|
||||
@@ -79,6 +80,7 @@ u32 pkg2_newkern_ini1_end;
|
||||
#define ID_SND_OFF_1000 0x34404
|
||||
#define ID_SND_OFF_1100 0x245B4
|
||||
#define ID_SND_OFF_1101 0x245B8
|
||||
#define ID_SND_OFF_1200 0x24CF4
|
||||
|
||||
#define ID_RCV_OFF_100 0x219F0
|
||||
#define ID_RCV_OFF_200 0x3D1A8
|
||||
@@ -93,6 +95,7 @@ u32 pkg2_newkern_ini1_end;
|
||||
#define ID_RCV_OFF_1000 0x322F8
|
||||
#define ID_RCV_OFF_1100 0x22B24
|
||||
#define ID_RCV_OFF_1101 0x22B28
|
||||
#define ID_RCV_OFF_1200 0x23424
|
||||
|
||||
static u32 PRC_ID_SND_100[] =
|
||||
{
|
||||
@@ -228,6 +231,20 @@ static u32 PRC_ID_RCV_1100[] =
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_1200[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF9404FEB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002C8, 0xF9401D08, 0xAA1603E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_1200 (FREE_CODE_OFF_1ST_1200 + sizeof(PRC_ID_SND_1200) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_1200[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94073EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400388, 0xF9401D08, 0xAA1C03E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
// Include kernel patches here, so we can utilize pkg1 id
|
||||
KERNEL_PATCHSET_DEF(_kernel_1_patchset,
|
||||
{ SVC_VERIFY_DS, 0x3764C, _NOP(), NULL }, // Disable SVC verifications
|
||||
@@ -427,7 +444,23 @@ KERNEL_PATCHSET_DEF(_kernel_1101_patchset,
|
||||
_B(FREE_CODE_OFF_2ND_1100 + sizeof(PRC_ID_RCV_1100), ID_RCV_OFF_1101 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
// Kernel sha256 hashes.
|
||||
KERNEL_PATCHSET_DEF(_kernel_12_patchset,
|
||||
{ SVC_GENERIC, 0x2FCB4, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x38440, _NOP(), NULL }, // Disable SVC verifications.
|
||||
{ DEBUG_MODE_EN, 0x45118, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch.
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_SYSM_INCR, 0x4809C, _MOVZW(21, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_1200, _B(ID_SND_OFF_1200, FREE_CODE_OFF_1ST_1200), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_1200, sizeof(PRC_ID_SND_1200) >> 2, PRC_ID_SND_1200}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_1200 + sizeof(PRC_ID_SND_1200), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_1200 + sizeof(PRC_ID_SND_1200), ID_SND_OFF_1200 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_1200, _B(ID_RCV_OFF_1200, FREE_CODE_OFF_2ND_1200), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_1200, sizeof(PRC_ID_RCV_1200) >> 2, PRC_ID_RCV_1200}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_1200 + sizeof(PRC_ID_RCV_1200), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_1200 + sizeof(PRC_ID_RCV_1200), ID_RCV_OFF_1200 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
// Kernel sha256 hashes. Offset 0x800 up to INI1 start.
|
||||
static const pkg2_kernel_id_t _pkg2_kernel_ids[] =
|
||||
{
|
||||
{ "\xb8\xc5\x0c\x68\x25\xa9\xb9\x5b", _kernel_1_patchset }, // 1.0.0
|
||||
@@ -444,6 +477,7 @@ static const pkg2_kernel_id_t _pkg2_kernel_ids[] =
|
||||
{ "\x21\xc1\xd7\x24\x8e\xcd\xbd\xa8", _kernel_10_patchset }, // 10.0.0. Kernel only.
|
||||
{ "\xD5\xD0\xBA\x5D\x52\xB9\x77\x85", _kernel_11_patchset }, // 11.0.0. Kernel only.
|
||||
{ "\xF8\x1E\xE0\x30\x3C\x7A\x08\x04", _kernel_1101_patchset },// 11.0.1. Kernel only.
|
||||
{ "\xA6\xD8\xFF\xF3\x67\x4A\x33\xFC", _kernel_12_patchset }, // 12.0.0. Kernel only.
|
||||
};
|
||||
|
||||
enum kip_offset_section
|
||||
@@ -463,6 +497,7 @@ enum kip_offset_section
|
||||
#define GET_KIP_PATCH_OFFSET(x) ((x) & KIP_PATCH_OFFSET_MASK)
|
||||
#define KPS(x) ((u32)(x) << KIP_PATCH_SECTION_SHIFT)
|
||||
|
||||
// All kip patch offsets are without the 0x100-sized header.
|
||||
static kip1_patch_t _fs_emummc[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 1, 0, "", "" },
|
||||
@@ -686,6 +721,19 @@ static kip1_patchset_t _fs_patches_1100[] =
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1200[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x13EA24, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x155368, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1200[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_1200 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
// SHA256 hashes.
|
||||
static kip1_id_t _kip_ids[] =
|
||||
@@ -728,6 +776,8 @@ static kip1_id_t _kip_ids[] =
|
||||
{ "FS", "\x16\x0D\x3E\x10\x4E\xAD\x61\x76", _fs_patches_1020 }, // FS 10.2.0 exfat
|
||||
{ "FS", "\xE3\x99\x15\x6E\x84\x4E\xB0\xAA", _fs_patches_1100 }, // FS 11.0.0
|
||||
{ "FS", "\x0B\xA1\x5B\xB3\x04\xB5\x05\x63", _fs_patches_1100 }, // FS 11.0.0 exfat
|
||||
{ "FS", "\xDC\x2A\x08\x49\x96\xBB\x3C\x01", _fs_patches_1200 }, // FS 12.0.0
|
||||
{ "FS", "\xD5\xA5\xBF\x36\x64\x0C\x49\xEA", _fs_patches_1200 }, // FS 12.0.0 exfat
|
||||
};
|
||||
|
||||
static kip1_id_t *_kip_id_sets = _kip_ids;
|
||||
@@ -1311,7 +1361,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
}
|
||||
currPatchset++;
|
||||
}
|
||||
if (emummc_patch_selected && !strncmp(_kip_id_sets[currKipIdx].name, "FS", 2))
|
||||
if (emummc_patch_selected && !strncmp(_kip_id_sets[currKipIdx].name, "FS", sizeof(ki->kip1->name)))
|
||||
{
|
||||
emummc_patch_selected = false;
|
||||
emu_cfg.fs_ver = currKipIdx;
|
||||
|
||||
@@ -86,9 +86,9 @@ static ini_kip_sec_t *_ini_create_kip_section(link_t *dst, ini_kip_sec_t *ksec,
|
||||
|
||||
int ini_patch_parse(link_t *dst, char *ini_path)
|
||||
{
|
||||
FIL fp;
|
||||
u32 lblen;
|
||||
char lbuf[512];
|
||||
FIL fp;
|
||||
ini_kip_sec_t *ksec = NULL;
|
||||
|
||||
// Open ini.
|
||||
|
||||
@@ -145,6 +145,7 @@ typedef struct _atm_fatal_error_ctx
|
||||
#define EXO_FLAG_USER_PMU BIT(4)
|
||||
#define EXO_FLAG_CAL0_BLANKING BIT(5)
|
||||
#define EXO_FLAG_CAL0_WRITES_SYS BIT(6)
|
||||
#define EXO_FLAG_ENABLE_USB3 BIT(7)
|
||||
|
||||
#define EXO_FW_VER(mj, mn, rv) (((mj) << 24) | ((mn) << 16) | ((rv) << 8))
|
||||
|
||||
@@ -152,6 +153,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
{
|
||||
u32 exo_fw_no = 0;
|
||||
u32 exo_flags = 0;
|
||||
bool usb3_force = false;
|
||||
bool user_debug = false;
|
||||
bool cal0_blanking = false;
|
||||
bool cal0_allow_writes_sys = false;
|
||||
@@ -167,17 +169,17 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
exo_fw_no = ctxt->pkg1_id->fuses - 1; // 3.0.1 - 7.0.1, 8.0.0 - 8.0.1.
|
||||
|
||||
if (!memcmp(ctxt->pkg1_id->id, "20190314172056", 8)) // 8.0.0 - 8.0.1.
|
||||
exo_fw_no++;
|
||||
exo_fw_no++;
|
||||
|
||||
if (!memcmp(ctxt->pkg1_id->id, "20210129111626", 8)) // 12.0.0.
|
||||
exo_fw_no++;
|
||||
|
||||
// Feed old exosphere target versioning to new.
|
||||
if (exo_new)
|
||||
{
|
||||
switch (exo_fw_no)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 1 ... 4:
|
||||
case 6:
|
||||
exo_fw_no = EXO_FW_VER(exo_fw_no, 0, 0);
|
||||
break;
|
||||
@@ -190,11 +192,8 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
case 7:
|
||||
exo_fw_no = EXO_FW_VER(6, 2, 0);
|
||||
break;
|
||||
case 8:
|
||||
exo_fw_no = EXO_FW_VER(7, 0, 0);
|
||||
break;
|
||||
case 9:
|
||||
exo_fw_no = EXO_FW_VER(8, 0, 0);
|
||||
case 8 ... 9:
|
||||
exo_fw_no = EXO_FW_VER(exo_fw_no - 1, 0, 0);
|
||||
break;
|
||||
case 10:
|
||||
exo_fw_no = EXO_FW_VER(8, 1, 0);
|
||||
@@ -205,11 +204,8 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
case 12:
|
||||
exo_fw_no = EXO_FW_VER(9, 1, 0);
|
||||
break;
|
||||
case 13:
|
||||
exo_fw_no = EXO_FW_VER(10, 0, 0);
|
||||
break;
|
||||
case 14:
|
||||
exo_fw_no = EXO_FW_VER(11, 0, 0);
|
||||
case 13 ... 15:
|
||||
exo_fw_no = EXO_FW_VER(exo_fw_no - 3, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -252,6 +248,34 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse usb mtim settings. Avoid parsing if it's overridden.
|
||||
if (ctxt->fss0_main_path && !ctxt->exo_ctx.usb3_force)
|
||||
{
|
||||
char set_path[256];
|
||||
strcpy(set_path, ctxt->fss0_main_path);
|
||||
strcat(set_path, "config/system_settings.ini");
|
||||
LIST_INIT(sys_settings);
|
||||
if (ini_parse(&ini_sections, set_path, false))
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
{
|
||||
// Only parse usb section.
|
||||
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "usb"))
|
||||
continue;
|
||||
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||
{
|
||||
if (!strcmp("usb30_force_enabled", kv->key))
|
||||
{
|
||||
usb3_force = !strcmp("u8!0x1", kv->val);
|
||||
break; // Only parse usb30_force_enabled key.
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To avoid problems, make private debug mode always on if not semi-stock.
|
||||
@@ -270,6 +294,11 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
if (ctxt->exo_ctx.user_pmu)
|
||||
exo_flags |= EXO_FLAG_USER_PMU;
|
||||
|
||||
// Enable USB 3.0. Check if system_settings ini value is overridden. If not, check if enabled in ini.
|
||||
if ((ctxt->exo_ctx.usb3_force && *ctxt->exo_ctx.usb3_force)
|
||||
|| (!ctxt->exo_ctx.usb3_force && usb3_force))
|
||||
exo_flags |= EXO_FLAG_ENABLE_USB3;
|
||||
|
||||
// Enable prodinfo blanking. Check if exo ini value is overridden. If not, check if enabled in exo ini.
|
||||
if ((ctxt->exo_ctx.cal0_blank && *ctxt->exo_ctx.cal0_blank)
|
||||
|| (!ctxt->exo_ctx.cal0_blank && cal0_blanking))
|
||||
|
||||
@@ -143,6 +143,7 @@ void check_power_off_from_hos()
|
||||
#define EXT_PAYLOAD_ADDR 0xC0000000
|
||||
#define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))
|
||||
#define COREBOOT_END_ADDR 0xD0000000
|
||||
#define COREBOOT_VER_OFF 0x41
|
||||
#define CBFS_DRAM_EN_ADDR 0x4003e000
|
||||
#define CBFS_DRAM_MAGIC 0x4452414D // "DRAM"
|
||||
|
||||
@@ -268,7 +269,12 @@ int launch_payload(char *path, bool update)
|
||||
else
|
||||
{
|
||||
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000);
|
||||
hw_reinit_workaround(true, 0);
|
||||
|
||||
// Get coreboot seamless display magic.
|
||||
u32 magic = 0;
|
||||
char *magic_ptr = buf + COREBOOT_VER_OFF;
|
||||
memcpy(&magic, magic_ptr + strlen(magic_ptr) - 4, 4);
|
||||
hw_reinit_workaround(true, magic);
|
||||
}
|
||||
|
||||
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
|
||||
@@ -1508,7 +1514,7 @@ ment_t ment_top[] = {
|
||||
MDEF_END()
|
||||
};
|
||||
|
||||
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.5.4", 0, 0 };
|
||||
menu_t menu_top = { ment_top, "hekate v5.5.5", 0, 0 };
|
||||
|
||||
extern void pivot_stack(u32 stack_top);
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
|
||||
|
||||
emummc_storage_read(NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf);
|
||||
|
||||
// Check if no GPT or more than max allowed entries.
|
||||
if (memcmp(&gpt_buf->header.signature, "EFI PART", 8) || gpt_buf->header.num_part_ents > 128)
|
||||
goto out;
|
||||
|
||||
for (u32 i = 0; i < gpt_buf->header.num_part_ents; i++)
|
||||
{
|
||||
emmc_part_t *part = (emmc_part_t *)calloc(sizeof(emmc_part_t), 1);
|
||||
@@ -54,6 +58,7 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
|
||||
list_append(gpt, &part->link);
|
||||
}
|
||||
|
||||
out:
|
||||
free(gpt_buf);
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,4 @@ void _minerva_do_over_temp_compensation(mtc_config_t *mtc_cfg);
|
||||
/* Over temp and periodic compensation, should not access EMC_MRR at the same time. */
|
||||
u32 _minerva_do_periodic_compensation(emc_table_t *mtc_table_entry);
|
||||
|
||||
/* Main function used to access all Minerva functions. */
|
||||
void _minerva_init(mtc_config_t *mtc_cfg, void* bp);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Minerva Training Cell
|
||||
* DRAM Training for Tegra X1 SoC. Supports LPDDR4.
|
||||
*
|
||||
* Copyright (c) 2018 CTCaer <ctcaer@gmail.com>
|
||||
* Copyright (c) 2018-2021 CTCaer <ctcaer@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -28,8 +28,9 @@
|
||||
#define EPRINTF(...)
|
||||
#define EPRINTFARGS(...)
|
||||
|
||||
#define MAX_FREQ_T210 1600000
|
||||
//#define OVERCLOCK_FREQ 1862400
|
||||
#define MAX_FREQ_T210 1600000
|
||||
//#define OVERCLOCK_FREQ 1862400
|
||||
//#define OVERCLOCK_VOLTAGE 1200000 // Default is 1100mV and in HOS 1125mV.
|
||||
|
||||
bool emc_2X_clk_src_is_pllmb;
|
||||
bool fsp_for_src_freq;
|
||||
@@ -1365,7 +1366,7 @@ static u32 _dvfs_power_ramp_down(bool flip_backward, emc_table_t *src_emc_table_
|
||||
|
||||
u32 pmacro_cmd_pad_drvforceon = pmacro_cmd_pad | 0x4000000;
|
||||
|
||||
u32 ramp_down_wait = src_clock_period * 12 / 1000;
|
||||
u32 ramp_down_wait = src_clock_period * 12;
|
||||
|
||||
_ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad_drvforceon, 0);
|
||||
_ccfifo_write(EMC_FBIO_CFG5, pmacro_cfg5 | 0x100, 12);
|
||||
@@ -1373,11 +1374,10 @@ static u32 _dvfs_power_ramp_down(bool flip_backward, emc_table_t *src_emc_table_
|
||||
if (src_clock_period >= 1000) // Dvfs high speed threshold.
|
||||
{
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xF800F800, (u32)(src_clk_per_pc + 19));
|
||||
ramp_down_wait = ramp_down_wait + 100 + (src_clock_period * 20 / 1000);
|
||||
ramp_down_wait += 100000 + (src_clock_period * 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
ramp_down_wait += 100;
|
||||
if (src_clock_period >= 416) // Iobrick dcc threshold.
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xFEEDFEED, (u32)src_clk_per_pc);
|
||||
else
|
||||
@@ -1388,8 +1388,7 @@ static u32 _dvfs_power_ramp_down(bool flip_backward, emc_table_t *src_emc_table_
|
||||
_ccfifo_write(EMC_PMACRO_DATA_PAD_TX_CTRL, pmacro_dq_pad, 0);
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xFEEDFEED, 0);
|
||||
}
|
||||
|
||||
ramp_down_wait += 200;
|
||||
ramp_down_wait += 300000;
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xFE40FE40, (u32)src_clk_per_pc);
|
||||
|
||||
if (src_clock_period >= 416) // Iobrick dcc threshold.
|
||||
@@ -1406,7 +1405,7 @@ static u32 _dvfs_power_ramp_down(bool flip_backward, emc_table_t *src_emc_table_
|
||||
_ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & 0xFFFFFFF0, (u32)src_clk_per_pc);
|
||||
else
|
||||
{
|
||||
ramp_down_wait += 400;
|
||||
ramp_down_wait += 400000;
|
||||
_ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & 0xFFFFFFFA, (u32)src_clk_per_pc);
|
||||
_ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & 0xFFFFFFF0, (u32)src_clk_per_pc);
|
||||
_ccfifo_write(0, 0, (u32)src_clk_per_pc);
|
||||
@@ -1477,49 +1476,49 @@ static u32 _dvfs_power_ramp_up(bool flip_backward, emc_table_t *src_emc_table_en
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 | 0x600, 0);
|
||||
_ccfifo_write(EMC_FBIO_CFG5, pmacro_cfg5 & 0xFFFFFEFF, 12);
|
||||
|
||||
ramp_up_wait = (dst_clock_period * 12) / 1000 + 0;
|
||||
ramp_up_wait = (dst_clock_period * 12) + 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & 0xA, 0);
|
||||
_ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & 0xF, (u32)dst_clk_per_pc);
|
||||
_ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & 0xF, dst_clk_per_pc);
|
||||
|
||||
if (dst_clock_period < 1000) // Dvfs high speed threshold.
|
||||
{
|
||||
if (dst_clock_period >= 416) // Iobrick dcc threshold.
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xFE40FE40, (u32)dst_clk_per_pc);
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xFE40FE40, dst_clk_per_pc);
|
||||
else
|
||||
{
|
||||
pmacro_cmd_pad_data = (pmacro_cmd_pad & 0xFEFEFDFD) | 0x4010200;
|
||||
pmacro_dq_pad = (pmacro_dq_pad & 0xFEFEFDFD) | 0x10200;
|
||||
_ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad_data, (u32)dst_clk_per_pc);
|
||||
_ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad_data, dst_clk_per_pc);
|
||||
_ccfifo_write(EMC_PMACRO_DATA_PAD_TX_CTRL, pmacro_dq_pad, 0);
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xFE40FE40, 0);
|
||||
}
|
||||
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xFEEDFEED, (u32)dst_clk_per_pc);
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xFEEDFEED, dst_clk_per_pc);
|
||||
|
||||
if (dst_clock_period >= 416) // Iobrick dcc threshold.
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1, (u32)dst_clk_per_pc);
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1, dst_clk_per_pc);
|
||||
else
|
||||
{
|
||||
pmacro_cmd_pad_data |= 0x1010202u;
|
||||
pmacro_dq_pad |= 0x1010202;
|
||||
_ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad_data, (u32)dst_clk_per_pc);
|
||||
_ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad_data, dst_clk_per_pc);
|
||||
_ccfifo_write(EMC_PMACRO_DATA_PAD_TX_CTRL, pmacro_dq_pad, 0);
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1, 0);
|
||||
}
|
||||
|
||||
_ccfifo_write(EMC_FBIO_CFG5, pmacro_cfg5 & 0xFFFFFEFF, (u32)(dst_clk_per_pc + 9));
|
||||
_ccfifo_write(EMC_FBIO_CFG5, pmacro_cfg5 & 0xFFFFFEFF, dst_clk_per_pc + 9);
|
||||
|
||||
ramp_up_wait = 500 + (dst_clock_period * 10) / 1000;
|
||||
ramp_up_wait = 500000 + (dst_clock_period * 10);
|
||||
}
|
||||
else // 1000 > dst_clock_period < 1666.
|
||||
{
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 | 0x6000600, (u32)dst_clk_per_pc);
|
||||
_ccfifo_write(EMC_FBIO_CFG5, pmacro_cfg5 & 0xFFFFFEFF, (u32)(dst_clk_per_pc + 9));
|
||||
_ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 | 0x6000600, dst_clk_per_pc);
|
||||
_ccfifo_write(EMC_FBIO_CFG5, pmacro_cfg5 & 0xFFFFFEFF, dst_clk_per_pc + 9);
|
||||
|
||||
ramp_up_wait = 200 + (dst_clock_period * 10) / 1000;
|
||||
ramp_up_wait = 200000 + (dst_clock_period * 10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1541,9 +1540,9 @@ static u32 _minerva_update_clock_tree_delay(emc_table_t *src_emc_entry, emc_tabl
|
||||
|
||||
u32 upd_type_bits = 1 << update_type;
|
||||
u32 dst_rate_mhz = dst_emc_entry->rate_khz / 1000;
|
||||
u32 src_rate_mhz_2x = (src_emc_entry->rate_khz / 1000) * 2;
|
||||
u32 src_rate_mhz = src_emc_entry->rate_khz / 1000;
|
||||
|
||||
u32 tval = 1000000 * _actual_osc_clocks(src_emc_entry->run_clocks);
|
||||
u32 tval = 1000000 * _actual_osc_clocks(src_emc_entry->run_clocks) / 2;
|
||||
|
||||
if (update_type > PERIODIC_TRAINING_UPDATE)
|
||||
return 0;
|
||||
@@ -1569,7 +1568,7 @@ static u32 _minerva_update_clock_tree_delay(emc_table_t *src_emc_entry, emc_tabl
|
||||
}
|
||||
}
|
||||
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch0_0);
|
||||
cval = tval / (src_rate_mhz * temp_ch0_0);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1601,11 +1600,11 @@ static u32 _minerva_update_clock_tree_delay(emc_table_t *src_emc_entry, emc_tabl
|
||||
if (tdelta < 0)
|
||||
tdelta = -tdelta;
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta * 128) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c0d0u0 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d0u0_idx / 100;
|
||||
|
||||
calc_td0_0:
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch0_1);
|
||||
cval = tval / (src_rate_mhz * temp_ch0_1);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1638,13 +1637,13 @@ calc_td0_0:
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta * 128) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c0d0u1 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d0u1_idx / 100;
|
||||
|
||||
calc_td1_0:
|
||||
if (channel1_enabled)
|
||||
{
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch1_0);
|
||||
cval = tval / (src_rate_mhz * temp_ch1_0);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1677,11 +1676,11 @@ calc_td1_0:
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta * 128) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c1d0u0 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d0u0_idx / 100;
|
||||
|
||||
calc_td1_1:
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch1_1);
|
||||
cval = tval / (src_rate_mhz * temp_ch1_1);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1714,7 +1713,7 @@ calc_td1_1:
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta * 128) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c1d0u1 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d0u1_idx / 100;
|
||||
}
|
||||
|
||||
@@ -1743,7 +1742,7 @@ calc_dev2:
|
||||
}
|
||||
}
|
||||
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch0_0);
|
||||
cval = tval / (src_rate_mhz * temp_ch0_0);
|
||||
switch (update_type )
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1776,11 +1775,11 @@ calc_dev2:
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta * 128) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c0d1u0 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d1u0_idx / 100;
|
||||
|
||||
calc_tmp_td0_1:
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch0_1);
|
||||
cval = tval / (src_rate_mhz * temp_ch0_1);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1813,13 +1812,13 @@ calc_tmp_td0_1:
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta * 128) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c0d1u1 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d1u1_idx / 100;
|
||||
|
||||
calc_tmp_td1_0:
|
||||
if (channel1_enabled)
|
||||
{
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch1_0);
|
||||
cval = tval / (src_rate_mhz * temp_ch1_0);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1852,11 +1851,11 @@ calc_tmp_td1_0:
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta * 128) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c1d1u0 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d1u0_idx / 100;
|
||||
|
||||
calc_tmp_td1_1:
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch1_1);
|
||||
cval = tval / (src_rate_mhz * temp_ch1_1);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1889,7 +1888,7 @@ calc_tmp_td1_1:
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta * 128) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c1d1u1 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d1u1_idx / 100;
|
||||
}
|
||||
|
||||
@@ -2143,8 +2142,8 @@ static u32 _minerva_apply_periodic_compensation_trimmer(emc_table_t *mtc_table_e
|
||||
|
||||
static bool _check_freq_changed(u32 dst_entry_rate_KHz, u32 dst_entry_clk_src_emc, u32 src_entry_rate_KHz, u32 src_entry_clk_src_emc)
|
||||
{
|
||||
s64 dst_div_clock;
|
||||
s64 src_div_clock;
|
||||
u64 dst_div_clock;
|
||||
u64 src_div_clock;
|
||||
u32 src_end_div_clk_ratio;
|
||||
|
||||
u32 src_entry_emc_2X_clk_src = src_entry_clk_src_emc >> EMC_2X_CLK_SRC_SHIFT;
|
||||
@@ -2555,7 +2554,7 @@ static void _save_train_results(emc_table_t *mtc_table_entry, u32 needs_training
|
||||
}
|
||||
}
|
||||
|
||||
u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u32 needs_training, u32 selected_clk_src_emc)
|
||||
static u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u32 needs_training, u32 selected_clk_src_emc)
|
||||
{
|
||||
u32 emc_dbg_o;
|
||||
u32 emc_pin_o;
|
||||
@@ -2568,8 +2567,8 @@ u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
u32 ramp_down_wait;
|
||||
u32 bg_regulator_mode_change;
|
||||
u32 mr13_flip_fspop = 0;
|
||||
u32 mr13_flip_fspwr = 0; //float
|
||||
u32 mr13_catr_enable = 0; //float
|
||||
u32 mr13_flip_fspwr = 0;
|
||||
u32 mr13_catr_enable;
|
||||
|
||||
/* needs_training LOBYTE table var */
|
||||
/*
|
||||
@@ -2604,8 +2603,8 @@ u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
u32 dram_type = EMC(EMC_FBIO_CFG5) & 3;
|
||||
u32 dram_dev_num = (MC(MC_EMEM_ADR_CFG) & 1) + 1;
|
||||
|
||||
u32 src_clock_period = 1000000000 / src_emc_entry->rate_khz;
|
||||
u32 dst_clock_period = 1000000000 / dst_emc_entry->rate_khz;
|
||||
u32 src_clock_period = 1000000000 / src_emc_entry->rate_khz; // In picoseconds.
|
||||
u32 dst_clock_period = 1000000000 / dst_emc_entry->rate_khz; // In picoseconds.
|
||||
|
||||
fsp_for_src_freq = !fsp_for_src_freq;
|
||||
|
||||
@@ -2615,11 +2614,11 @@ u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
return 5;
|
||||
}
|
||||
|
||||
u32 tFC_lpddr4 = dst_emc_entry->dram_timings.t_fc_lpddr4;
|
||||
s32 tZQCAL_lpddr4 = 1000;
|
||||
u32 tFC_lpddr4 = dst_emc_entry->dram_timings.t_fc_lpddr4 * 1000;
|
||||
u32 tZQCAL_lpddr4 = 1000000;
|
||||
if (src_clock_period <= 2000)
|
||||
tZQCAL_lpddr4 = 1000 - tFC_lpddr4;
|
||||
s32 tZQCAL_lpddr4_fc_adj = tZQCAL_lpddr4 * 1000 / dst_clock_period;
|
||||
tZQCAL_lpddr4 -= tFC_lpddr4;
|
||||
s32 tZQCAL_lpddr4_fc_adj = tZQCAL_lpddr4 / dst_clock_period;
|
||||
|
||||
// Step 1 - Pre DVFS SW sequence.
|
||||
EPRINTF("Step 1");
|
||||
@@ -2672,7 +2671,7 @@ u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
|
||||
u32 adelta = _minerva_periodic_compensation_handler(src_emc_entry, dst_emc_entry, dram_dev_num, channel1_enabled, DVFS_SEQUENCE);
|
||||
|
||||
if (((dst_emc_entry->rate_khz / 1000) << 7) * adelta / 1000000 > dst_emc_entry->tree_margin)
|
||||
if (((dst_emc_entry->rate_khz / 1000) * 128) * adelta / 1000000 > dst_emc_entry->tree_margin)
|
||||
compensate_trimmer_applicable = true;
|
||||
}
|
||||
|
||||
@@ -2759,16 +2758,16 @@ u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
u32 W2P_war = 0;
|
||||
|
||||
u32 nRTP = 8; // <= 1066MHz.
|
||||
if (src_clock_period < 3759 // 1000 / 266MHz.
|
||||
&& src_clock_period < 1876 // 1000 / 533MHz.
|
||||
&& src_clock_period < 1250 // 1000 / 800MHz.
|
||||
&& src_clock_period < 938) // 1000 / 1066MHz.
|
||||
if ( src_clock_period < 1000000 / 266
|
||||
&& src_clock_period < 1000000 / 533
|
||||
&& src_clock_period < 1000000 / 800
|
||||
&& src_clock_period < 1000000 / 1066 )
|
||||
nRTP = 10; // 1067MHz < x <= 1333MHz.
|
||||
if (src_clock_period < 750) // 1000 / 1333MHz.
|
||||
if (src_clock_period < 1000000 / 1333)
|
||||
nRTP = 12; // 1333MHz < x <= 1600MHz.
|
||||
if (src_clock_period < 625) // 1000 / 1600MHz.
|
||||
if (src_clock_period < 1000000 / 1600)
|
||||
nRTP = 14; // 1600MHz < x <= 1866MHz.
|
||||
if (src_clock_period < 535) // 1000 / 1866MHz.
|
||||
if (src_clock_period < 1000000 / 1866)
|
||||
nRTP = 16; // > 1866MHz
|
||||
|
||||
u32 tRPST = (src_emc_entry->emc_mrw >> 7) & 1;
|
||||
@@ -2916,24 +2915,24 @@ u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
{
|
||||
switch ( reg_addr )
|
||||
{
|
||||
case EMC_PMACRO_AUTOCAL_CFG_COMMON:
|
||||
reg_val |= 0x10000;
|
||||
break;
|
||||
case EMC_PMACRO_DATA_PAD_TX_CTRL:
|
||||
reg_val &= 0xFEFEFDFD;
|
||||
break;
|
||||
case EMC_PMACRO_CMD_PAD_TX_CTRL:
|
||||
reg_val = (reg_val & 0xFAFEFDFD) | 0x4000000;
|
||||
break;
|
||||
case EMC_PMACRO_BRICK_CTRL_RFU1:
|
||||
reg_val &= 0xF800F800;
|
||||
break;
|
||||
case EMC_PMACRO_COMMON_PAD_TX_CTRL:
|
||||
reg_val &= 0xFFFFFFF0;
|
||||
break;
|
||||
case EMC_TRAINING_CTRL:
|
||||
reg_val |= needs_swap_rank_training << 14;// bit15 is TR_IN_SELF_REFRESH
|
||||
break;
|
||||
case EMC_PMACRO_AUTOCAL_CFG_COMMON:
|
||||
reg_val |= 0x10000;
|
||||
break;
|
||||
case EMC_PMACRO_DATA_PAD_TX_CTRL:
|
||||
reg_val &= 0xFEFEFDFD;
|
||||
break;
|
||||
case EMC_PMACRO_CMD_PAD_TX_CTRL:
|
||||
reg_val = (reg_val & 0xFAFEFDFD) | 0x4000000;
|
||||
break;
|
||||
case EMC_PMACRO_BRICK_CTRL_RFU1:
|
||||
reg_val &= 0xF800F800;
|
||||
break;
|
||||
case EMC_PMACRO_COMMON_PAD_TX_CTRL:
|
||||
reg_val &= 0xFFFFFFF0;
|
||||
break;
|
||||
case EMC_TRAINING_CTRL:
|
||||
reg_val |= needs_swap_rank_training << 14;// bit15 is TR_IN_SELF_REFRESH
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3087,7 +3086,7 @@ u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
EPRINTF("Step 10");
|
||||
_ccfifo_write(EMC_SELF_REF, 0x101, 0);
|
||||
|
||||
if (needs_ca_or_cavref_training < (src_clock_period <= 2000))
|
||||
if (!needs_ca_or_cavref_training && (src_clock_period <= 2000))
|
||||
{
|
||||
_ccfifo_write(EMC_MRW3, mr13_flip_fspwr ^ 0x40, 0);
|
||||
_ccfifo_write(EMC_MRW6, (src_emc_entry->burst_regs.emc_mrw6_idx & 0xC0C0) | (dst_emc_entry->burst_regs.emc_mrw6_idx & 0xFFFF3F3F), 0);
|
||||
@@ -3107,7 +3106,7 @@ u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
}
|
||||
|
||||
emc_dbg_val = emc_dbg_o;
|
||||
u32 tRP_src_timing = src_emc_entry->dram_timings.t_rp * 1000 / src_clock_period;
|
||||
u32 tRP_src_timing = (src_emc_entry->dram_timings.t_rp * 1000) / src_clock_period;
|
||||
bool in_self_refresh = false;
|
||||
u32 ref_delay = 0;
|
||||
|
||||
@@ -3135,7 +3134,7 @@ u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
else
|
||||
{
|
||||
_ccfifo_write(EMC_MRW3, mr13_flip_fspop | 8, tRP_src_timing);
|
||||
ref_delay = tFC_lpddr4 * 1000 / src_clock_period;
|
||||
ref_delay = tFC_lpddr4 / src_clock_period;
|
||||
}
|
||||
|
||||
_ccfifo_write(EMC_INTSTATUS, 0, ref_delay);
|
||||
@@ -3190,10 +3189,10 @@ u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
s32 T_PDEX_timing = div_o3(dst_emc_entry->dram_timings.t_pdex * 1000, dst_clock_period);
|
||||
|
||||
if (src_clock_period > 2000)
|
||||
zq_latch_dvfs_wait_time = tZQCAL_lpddr4_fc_adj - T_PDEX_timing;
|
||||
zq_latch_dvfs_wait_time = (s32)tZQCAL_lpddr4_fc_adj - T_PDEX_timing;
|
||||
else
|
||||
zq_latch_dvfs_wait_time =
|
||||
tZQCAL_lpddr4_fc_adj - (ramp_up_wait + ramp_down_wait) * 1000 / dst_clock_period;
|
||||
(s32)tZQCAL_lpddr4_fc_adj - (ramp_up_wait + ramp_down_wait) / dst_clock_period;
|
||||
|
||||
if (dram_dev_num == ONE_RANK)
|
||||
{
|
||||
@@ -3394,8 +3393,8 @@ step_19_2:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ramp_up_wait <= 1250)
|
||||
bg_regulator_switch_complete_wait_clks = (1250 - ramp_up_wait) * 1000 / dst_clock_period;
|
||||
if (ramp_up_wait <= 1250000)
|
||||
bg_regulator_switch_complete_wait_clks = (1250000 - ramp_up_wait) / dst_clock_period;
|
||||
_ccfifo_write(EMC_PMACRO_BG_BIAS_CTRL_0,
|
||||
dst_emc_entry->burst_regs.emc_pmacro_bg_bias_ctrl_0_idx, bg_regulator_switch_complete_wait_clks);
|
||||
}
|
||||
@@ -3419,7 +3418,8 @@ step_19_2:
|
||||
|
||||
// Step 22 - Restore EMC_CFG_PIPE_CLK.
|
||||
EPRINTF("Step 22");
|
||||
_ccfifo_write(EMC_SEL_DPD_CTRL, src_emc_entry->emc_sel_dpd_ctrl, 0);
|
||||
if (needs_tristate_training)
|
||||
_ccfifo_write(EMC_SEL_DPD_CTRL, src_emc_entry->emc_sel_dpd_ctrl, 0);
|
||||
|
||||
_ccfifo_write(EMC_DBG, emc_dbg_o, 0);
|
||||
_ccfifo_write(EMC_CFG_PIPE_CLK, emc_cfg_pipe_clk_o, 0);
|
||||
@@ -3711,6 +3711,7 @@ u32 _minerva_do_periodic_compensation(emc_table_t *mtc_table_entry)
|
||||
if (channel1_enabled)
|
||||
_wait_emc_status(EMC_EMC_STATUS, IN_SELF_REFRESH_MASK, 0, EMC_CH1);
|
||||
|
||||
// Wait for request FIFO to get empty.
|
||||
//_wait_emc_status(EMC_EMC_STATUS, REQ_FIFO_EMPTY, 0, EMC_CH0); //v1.6
|
||||
//if (channel1_enabled)
|
||||
// _wait_emc_status(EMC_EMC_STATUS, REQ_FIFO_EMPTY, 0, EMC_CH1); //v1.6
|
||||
@@ -3728,7 +3729,7 @@ u32 _minerva_do_periodic_compensation(emc_table_t *mtc_table_entry)
|
||||
u32 adelta = _minerva_update_clock_tree_delay(mtc_table_entry, mtc_table_entry, dram_dev_num, channel1_enabled, PERIODIC_TRAINING_UPDATE);
|
||||
|
||||
// Step 5 - Apply compensation w.r.t. trained values (if clock tree has drifted more than the set margin).
|
||||
if (adelta && ((mtc_table_entry->rate_khz / 1000) << 7) * adelta / 1000000 > mtc_table_entry->tree_margin)
|
||||
if (adelta && ((mtc_table_entry->rate_khz / 1000) * 128) * adelta / 1000000 > mtc_table_entry->tree_margin)
|
||||
{
|
||||
for (u32 i = 0; i < 10; i++)
|
||||
{
|
||||
@@ -3752,7 +3753,7 @@ u32 _minerva_do_periodic_compensation(emc_table_t *mtc_table_entry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 _minerva_set_rate(mtc_config_t *mtc_cfg)
|
||||
static u32 _minerva_set_rate(mtc_config_t *mtc_cfg)
|
||||
{
|
||||
u32 src_emc_entry_idx = 999;
|
||||
u32 dst_emc_entry_idx = 999;
|
||||
@@ -3876,7 +3877,7 @@ static void _minerva_get_table(mtc_config_t *mtc_cfg)
|
||||
mtc_cfg->init_done = MTC_INIT_MAGIC;
|
||||
}
|
||||
|
||||
void _minerva_init(mtc_config_t *mtc_cfg, void* bp)
|
||||
void _minerva_init(mtc_config_t *mtc_cfg, bdkParams_t bp)
|
||||
{
|
||||
EPRINTF("-- Minerva Training Cell --");
|
||||
|
||||
@@ -3887,7 +3888,14 @@ void _minerva_init(mtc_config_t *mtc_cfg, void* bp)
|
||||
if (mtc_cfg->init_done != MTC_INIT_MAGIC)
|
||||
{
|
||||
if (mtc_cfg->init_done == MTC_NEW_MAGIC)
|
||||
{
|
||||
_minerva_get_table(mtc_cfg);
|
||||
#ifdef OVERCLOCK_VOLTAGE
|
||||
// Set SD1 regulator voltage.
|
||||
if ((bp->extension_magic & 0xF0FFFFFF) == IANOS_EXT0)
|
||||
bp->reg_voltage_set(1, OVERCLOCK_VOLTAGE);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -527,9 +527,9 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part
|
||||
if (resized_count)
|
||||
{
|
||||
// Get USER partition info.
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, storage);
|
||||
emmc_part_t *user_part = nx_emmc_part_find(&gpt, "USER");
|
||||
LIST_INIT(gpt_parsed);
|
||||
nx_emmc_gpt_parse(&gpt_parsed, storage);
|
||||
emmc_part_t *user_part = nx_emmc_part_find(&gpt_parsed, "USER");
|
||||
if (!user_part)
|
||||
{
|
||||
s_printf(gui->txt_buf, "\n#FFDD00 USER partition not found!#\n");
|
||||
@@ -541,7 +541,7 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part
|
||||
|
||||
user_offset = user_part->lba_start;
|
||||
part->lba_end = user_offset - 1;
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
nx_emmc_gpt_free(&gpt_parsed);
|
||||
}
|
||||
|
||||
u32 totalSectors = part->lba_end - part->lba_start + 1;
|
||||
@@ -651,6 +651,8 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part
|
||||
|
||||
if (resized_count)
|
||||
{
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, "Done!\n");
|
||||
|
||||
// Calculate USER size and set it for FatFS.
|
||||
u32 user_sectors = resized_count - user_offset - 33;
|
||||
disk_set_info(DRIVE_EMU, SET_SECTOR_COUNT, &user_sectors);
|
||||
@@ -662,7 +664,7 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part
|
||||
strcpy(user_part.name, "USER");
|
||||
nx_emmc_bis_init(&user_part, true, sd_sector_off);
|
||||
|
||||
s_printf(gui->txt_buf, "\nFormatting USER...\n");
|
||||
s_printf(gui->txt_buf, "Formatting USER... \n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -676,71 +678,75 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part
|
||||
|
||||
if (mkfs_error)
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FF0000 USER format failed (%d)...#\nPlease try again...\n", mkfs_error);
|
||||
s_printf(gui->txt_buf, "#FF0000 Failed (%d)!#\nPlease try again...\n", mkfs_error);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, "Done!\n");
|
||||
|
||||
// Flush BIS cache, deinit, clear BIS keys slots and reinstate SBK.
|
||||
nx_emmc_bis_end();
|
||||
hos_bis_keys_clear();
|
||||
|
||||
s_printf(gui->txt_buf, "Writing new GPT...\n");
|
||||
s_printf(gui->txt_buf, "Writing new GPT... ");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
// Read MBR, GPT and backup GPT.
|
||||
mbr_t mbr;
|
||||
gpt_t gpt_main;
|
||||
gpt_t *gpt = calloc(1, sizeof(gpt_t));
|
||||
gpt_header_t gpt_hdr_backup;
|
||||
sdmmc_storage_read(storage, 0, 1, &mbr);
|
||||
sdmmc_storage_read(storage, 1, sizeof(gpt_t) >> 9, &gpt_main);
|
||||
sdmmc_storage_read(storage, gpt_main.header.alt_lba, 1, &gpt_hdr_backup);
|
||||
sdmmc_storage_read(storage, 1, sizeof(gpt_t) >> 9, gpt);
|
||||
sdmmc_storage_read(storage, gpt->header.alt_lba, 1, &gpt_hdr_backup);
|
||||
|
||||
// Find USER partition.
|
||||
u32 gpt_entry_idx = 0;
|
||||
for (gpt_entry_idx = 0; gpt_entry_idx < gpt_main.header.num_part_ents; gpt_entry_idx++)
|
||||
if (!memcmp(gpt_main.entries[gpt_entry_idx].name, (char[]) { 'U', 0, 'S', 0, 'E', 0, 'R', 0 }, 8))
|
||||
for (gpt_entry_idx = 0; gpt_entry_idx < gpt->header.num_part_ents; gpt_entry_idx++)
|
||||
if (!memcmp(gpt->entries[gpt_entry_idx].name, (char[]) { 'U', 0, 'S', 0, 'E', 0, 'R', 0 }, 8))
|
||||
break;
|
||||
|
||||
if (gpt_entry_idx >= gpt_main.header.num_part_ents)
|
||||
if (gpt_entry_idx >= gpt->header.num_part_ents)
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FF0000 No USER partition...#\nPlease try again...\n");
|
||||
s_printf(gui->txt_buf, "\n#FF0000 No USER partition...#\nPlease try again...\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
free(gpt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set new emuMMC size and USER size.
|
||||
mbr.partitions[0].size_sct = resized_count;
|
||||
gpt_main.entries[gpt_entry_idx].lba_end = user_offset + user_sectors - 1;
|
||||
gpt->entries[gpt_entry_idx].lba_end = user_offset + user_sectors - 1;
|
||||
|
||||
// Update Main GPT.
|
||||
gpt_main.header.alt_lba = resized_count - 1;
|
||||
gpt_main.header.last_use_lba = resized_count - 34;
|
||||
gpt_main.header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt_main.entries, sizeof(gpt_entry_t) * gpt_main.header.num_part_ents);
|
||||
gpt_main.header.crc32 = 0; // Set to 0 for calculation.
|
||||
gpt_main.header.crc32 = crc32_calc(0, (const u8 *)&gpt_main.header, gpt_main.header.size);
|
||||
gpt->header.alt_lba = resized_count - 1;
|
||||
gpt->header.last_use_lba = resized_count - 34;
|
||||
gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, sizeof(gpt_entry_t) * gpt->header.num_part_ents);
|
||||
gpt->header.crc32 = 0; // Set to 0 for calculation.
|
||||
gpt->header.crc32 = crc32_calc(0, (const u8 *)&gpt->header, gpt->header.size);
|
||||
|
||||
// Update Backup GPT.
|
||||
gpt_hdr_backup.my_lba = resized_count - 1;
|
||||
gpt_hdr_backup.part_ent_lba = resized_count - 33;
|
||||
gpt_hdr_backup.part_ents_crc32 = gpt_main.header.part_ents_crc32;
|
||||
gpt_hdr_backup.part_ents_crc32 = gpt->header.part_ents_crc32;
|
||||
gpt_hdr_backup.crc32 = 0; // Set to 0 for calculation.
|
||||
gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size);
|
||||
|
||||
// Write main GPT.
|
||||
sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_main.header.my_lba, sizeof(gpt_t) >> 9, &gpt_main);
|
||||
sdmmc_storage_write(&sd_storage, sd_sector_off + gpt->header.my_lba, sizeof(gpt_t) >> 9, gpt);
|
||||
|
||||
// Write backup GPT partition table.
|
||||
sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt_main.entries);
|
||||
sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt->entries);
|
||||
|
||||
// Write backup GPT header.
|
||||
sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup);
|
||||
|
||||
// Write MBR.
|
||||
sdmmc_storage_write(&sd_storage, sd_sector_off, 1, &mbr);
|
||||
|
||||
free(gpt);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -703,7 +703,7 @@ static lv_res_t _create_emummc_migrate_action(lv_obj_t * btns, const char * txt)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found SD Partition based emuMMC!#\n\n"
|
||||
"#FF8000 Do you want to repair the config for it?#\n");
|
||||
"#FF8000 Do you want to repair the config and partition type for it?#\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig3_action);
|
||||
}
|
||||
else if (em_raw && em_file)
|
||||
|
||||
@@ -943,7 +943,16 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
|
||||
touch_panel = touch_get_panel_vendor();
|
||||
if (touch_panel)
|
||||
strcat(txt_buf, touch_panel->vendor);
|
||||
{
|
||||
if (touch_panel->idx == -2) // Touch panel not found, print gpios.
|
||||
{
|
||||
s_printf(txt_buf + strlen(txt_buf), "%2X%2X%2X #FFDD00 Contact me!#",
|
||||
touch_panel->gpio0, touch_panel->gpio1, touch_panel->gpio2);
|
||||
touch_panel = NULL;
|
||||
}
|
||||
else
|
||||
strcat(txt_buf, touch_panel->vendor);
|
||||
}
|
||||
else
|
||||
strcat(txt_buf, "Unknown #FFDD00 Contact me!#");
|
||||
|
||||
@@ -982,6 +991,7 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
break;
|
||||
case 0x32000501:
|
||||
case 0x33000502:
|
||||
case 0x33000503:
|
||||
strcat(txt_buf, "4CD UNKN");
|
||||
if (touch_panel)
|
||||
panel_ic_paired = touch_panel->idx == 4;
|
||||
@@ -994,6 +1004,8 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
s_printf(txt_buf + strlen(txt_buf), " - %s)\n#FF8000 FTB ver:# %04X\n#FF8000 FW rev:# %04X",
|
||||
panel_ic_paired ? "Paired" : "#FFDD00 Error#", touch_fw.ftb_ver, touch_fw.fw_rev);
|
||||
}
|
||||
else
|
||||
strcat(txt_buf, "\n\n#FFDD00 Failed to get touch info!#");
|
||||
|
||||
// Check if patched unit.
|
||||
if (!fuse_check_patched_rcm())
|
||||
@@ -1258,6 +1270,9 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
if (sd_bench)
|
||||
{
|
||||
storage = &sd_storage;
|
||||
|
||||
// Re-initialize to update trimmers.
|
||||
sd_end();
|
||||
res = !sd_mount();
|
||||
}
|
||||
else
|
||||
@@ -1272,6 +1287,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
lv_mbox_set_text(mbox, "#FFDD00 Failed to init Storage!#");
|
||||
else
|
||||
{
|
||||
int error = 0;
|
||||
u32 iters = 3;
|
||||
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, 0x8000); // Align to 16MB.
|
||||
if (storage->sec_cnt < 0xC00000)
|
||||
@@ -1292,7 +1308,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
while (data_remaining)
|
||||
{
|
||||
u32 time_taken = get_tmr_us();
|
||||
sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||
error = !sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||
time_taken = get_tmr_us() - time_taken;
|
||||
timer += time_taken;
|
||||
|
||||
@@ -1309,8 +1325,11 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
prevPct = pct;
|
||||
|
||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
break;
|
||||
error = -1;
|
||||
}
|
||||
|
||||
if (error)
|
||||
goto error;
|
||||
}
|
||||
lv_bar_set_value(bar, 100);
|
||||
|
||||
@@ -1333,7 +1352,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
while (data_remaining)
|
||||
{
|
||||
u32 time_taken = get_tmr_us();
|
||||
sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||
error = !sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||
time_taken = get_tmr_us() - time_taken;
|
||||
timer += time_taken;
|
||||
|
||||
@@ -1350,8 +1369,11 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
prevPct = pct;
|
||||
|
||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
break;
|
||||
error = -1;
|
||||
}
|
||||
|
||||
if (error)
|
||||
goto error;
|
||||
}
|
||||
lv_bar_set_value(bar, 100);
|
||||
|
||||
@@ -1388,7 +1410,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
while (data_remaining)
|
||||
{
|
||||
u32 time_taken = get_tmr_us();
|
||||
sdmmc_storage_read(storage, sector + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||
error = !sdmmc_storage_read(storage, sector + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||
time_taken = get_tmr_us() - time_taken;
|
||||
timer += time_taken;
|
||||
|
||||
@@ -1405,7 +1427,13 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
prevPct = pct;
|
||||
|
||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
break;
|
||||
error = -1;
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
free(random_offsets);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
lv_bar_set_value(bar, 100);
|
||||
@@ -1416,6 +1444,8 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
s_printf(txt_buf + strlen(txt_buf),
|
||||
" Random 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
|
||||
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
|
||||
if (iter_curr == iters - 1)
|
||||
txt_buf[strlen(txt_buf) - 1] = 0; // Cut off last line change.
|
||||
lv_label_set_text(lbl_status, txt_buf);
|
||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
@@ -1423,6 +1453,18 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
free(random_offsets);
|
||||
}
|
||||
|
||||
error:
|
||||
if (error)
|
||||
{
|
||||
if (error == -1)
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n#FFDD00 Aborted!#");
|
||||
else
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n#FFDD00 IO Error occurred!#");
|
||||
|
||||
lv_label_set_text(lbl_status, txt_buf);
|
||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
}
|
||||
|
||||
lv_obj_del(bar);
|
||||
|
||||
if (sd_bench)
|
||||
|
||||
@@ -50,7 +50,7 @@ typedef struct _partition_ctxt_t
|
||||
|
||||
bool emu_double;
|
||||
|
||||
mbr_t *mbr_old;
|
||||
mbr_t mbr_old;
|
||||
|
||||
lv_obj_t *bar_hos;
|
||||
lv_obj_t *bar_emu;
|
||||
@@ -222,17 +222,15 @@ static int _backup_and_restore_files(char *path, u32 *total_files, u32 *total_si
|
||||
|
||||
static void _prepare_and_flash_mbr_gpt()
|
||||
{
|
||||
u8 random_number[16];
|
||||
mbr_t mbr;
|
||||
gpt_t gpt = { 0 };
|
||||
gpt_header_t gpt_hdr_backup = { 0 };
|
||||
u8 random_number[16];
|
||||
|
||||
// Read current MBR.
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, &mbr);
|
||||
|
||||
// Copy over metadata if they exist.
|
||||
if (part_info.mbr_old->bootstrap[0x80])
|
||||
memcpy(&mbr.bootstrap[0x80], &part_info.mbr_old->bootstrap[0x80], 304);
|
||||
if (*(u32 *)&part_info.mbr_old.bootstrap[0x80])
|
||||
memcpy(&mbr.bootstrap[0x80], &part_info.mbr_old.bootstrap[0x80], 304);
|
||||
|
||||
// Clear the first 16MB.
|
||||
memset((void *)SDMMC_UPPER_BUFFER, 0, 0x8000);
|
||||
@@ -275,49 +273,52 @@ static void _prepare_and_flash_mbr_gpt()
|
||||
|
||||
if (part_info.and_size)
|
||||
{
|
||||
gpt_t *gpt = calloc(1, sizeof(gpt_t));
|
||||
gpt_header_t gpt_hdr_backup = { 0 };
|
||||
|
||||
mbr.partitions[mbr_idx].type = 0xEE; // GPT protective partition.
|
||||
mbr.partitions[mbr_idx].start_sct = 1;
|
||||
mbr.partitions[mbr_idx].size_sct = sd_storage.sec_cnt - 1;
|
||||
mbr_idx++;
|
||||
|
||||
// Set GPT header.
|
||||
memcpy(&gpt.header.signature, "EFI PART", 8);
|
||||
gpt.header.revision = 0x10000;
|
||||
gpt.header.size = 92;
|
||||
gpt.header.my_lba = 1;
|
||||
gpt.header.alt_lba = sd_storage.sec_cnt - 1;
|
||||
gpt.header.first_use_lba = (sizeof(mbr_t) + sizeof(gpt_t)) >> 9;
|
||||
gpt.header.last_use_lba = sd_storage.sec_cnt - 0x800 - 1; // sd_storage.sec_cnt - 33 is start of backup gpt partition entries.
|
||||
memcpy(&gpt->header.signature, "EFI PART", 8);
|
||||
gpt->header.revision = 0x10000;
|
||||
gpt->header.size = 92;
|
||||
gpt->header.my_lba = 1;
|
||||
gpt->header.alt_lba = sd_storage.sec_cnt - 1;
|
||||
gpt->header.first_use_lba = (sizeof(mbr_t) + sizeof(gpt_t)) >> 9;
|
||||
gpt->header.last_use_lba = sd_storage.sec_cnt - 0x800 - 1; // sd_storage.sec_cnt - 33 is start of backup gpt partition entries.
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.header.disk_guid, random_number, 10);
|
||||
memcpy(gpt.header.disk_guid + 10, "NYXGPT", 6);
|
||||
gpt.header.part_ent_lba = 2;
|
||||
gpt.header.part_ent_size = 128;
|
||||
memcpy(gpt->header.disk_guid, random_number, 10);
|
||||
memcpy(gpt->header.disk_guid + 10, "NYXGPT", 6);
|
||||
gpt->header.part_ent_lba = 2;
|
||||
gpt->header.part_ent_size = 128;
|
||||
|
||||
// Set GPT partitions.
|
||||
u8 basic_part_guid[] = { 0xA2, 0xA0, 0xD0, 0xEB, 0xE5, 0xB9, 0x33, 0x44, 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 };
|
||||
memcpy(gpt.entries[0].type_guid, basic_part_guid, 16);
|
||||
memcpy(gpt->entries[0].type_guid, basic_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[0].part_guid, random_number, 16);
|
||||
memcpy(gpt->entries[0].part_guid, random_number, 16);
|
||||
|
||||
// Clear non-standard Windows MBR attributes. bit4: Read only, bit5: Shadow copy, bit6: Hidden, bit7: No drive letter.
|
||||
gpt.entries[0].part_guid[7] = 0;
|
||||
gpt->entries[0].part_guid[7] = 0;
|
||||
|
||||
gpt.entries[0].lba_start = mbr.partitions[0].start_sct;
|
||||
gpt.entries[0].lba_end = mbr.partitions[0].start_sct + mbr.partitions[0].size_sct - 1;
|
||||
memcpy(gpt.entries[0].name, (char[]) { 'h', 0, 'o', 0, 's', 0, '_', 0, 'd', 0, 'a', 0, 't', 0, 'a', 0 }, 16);
|
||||
gpt->entries[0].lba_start = mbr.partitions[0].start_sct;
|
||||
gpt->entries[0].lba_end = mbr.partitions[0].start_sct + mbr.partitions[0].size_sct - 1;
|
||||
memcpy(gpt->entries[0].name, (char[]) { 'h', 0, 'o', 0, 's', 0, '_', 0, 'd', 0, 'a', 0, 't', 0, 'a', 0 }, 16);
|
||||
|
||||
u8 gpt_idx = 1;
|
||||
u32 curr_part_lba = 0x8000 + ((u32)part_info.hos_size << 11);
|
||||
u8 android_part_guid[] = { 0xAF, 0x3D, 0xC6, 0x0F, 0x83, 0x84, 0x72, 0x47, 0x8E, 0x79, 0x3D, 0x69, 0xD8, 0x47, 0x7D, 0xE4 };
|
||||
if (part_info.l4t_size)
|
||||
{
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.l4t_size << 11) - 1;
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'l', 0, '4', 0, 't', 0 }, 6);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + (part_info.l4t_size << 11) - 1;
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'l', 0, '4', 0, 't', 0 }, 6);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
|
||||
curr_part_lba += (part_info.l4t_size << 11);
|
||||
@@ -325,89 +326,89 @@ static void _prepare_and_flash_mbr_gpt()
|
||||
}
|
||||
|
||||
// Android Vendor partition.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x200000 - 1; // 1GB.
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'v', 0, 'e', 0, 'n', 0, 'd', 0, 'o', 0, 'r', 0 }, 12);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + 0x200000 - 1; // 1GB.
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'v', 0, 'e', 0, 'n', 0, 'd', 0, 'o', 0, 'r', 0 }, 12);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
curr_part_lba += 0x200000;
|
||||
gpt_idx++;
|
||||
|
||||
// Android System partition.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x400000 - 1; // 2GB.
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'A', 0, 'P', 0, 'P', 0 }, 6);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + 0x400000 - 1; // 2GB.
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'A', 0, 'P', 0, 'P', 0 }, 6);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
curr_part_lba += 0x400000;
|
||||
gpt_idx++;
|
||||
|
||||
// Android Linux Kernel partition.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x10000 - 1; // 32MB.
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + 0x10000 - 1; // 32MB.
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
curr_part_lba += 0x10000;
|
||||
gpt_idx++;
|
||||
|
||||
// Android Recovery partition.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x20000 - 1; // 64MB.
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + 0x20000 - 1; // 64MB.
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
curr_part_lba += 0x20000;
|
||||
gpt_idx++;
|
||||
|
||||
// Android Device Tree Reference partition.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x800 - 1; // 1MB.
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'D', 0, 'T', 0, 'B', 0 }, 6);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + 0x800 - 1; // 1MB.
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'D', 0, 'T', 0, 'B', 0 }, 6);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
curr_part_lba += 0x800;
|
||||
gpt_idx++;
|
||||
|
||||
// Android Encryption partition.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x8000 - 1; // 16MB.
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'M', 0, 'D', 0, 'A', 0 }, 6);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + 0x8000 - 1; // 16MB.
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'M', 0, 'D', 0, 'A', 0 }, 6);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x8000, (void *)SDMMC_UPPER_BUFFER); // Clear 16MB.
|
||||
curr_part_lba += 0x8000;
|
||||
gpt_idx++;
|
||||
|
||||
// Android Cache partition.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x15E000 - 1; // 700MB.
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'C', 0, 'A', 0, 'C', 0 }, 6);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + 0x15E000 - 1; // 700MB.
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'C', 0, 'A', 0, 'C', 0 }, 6);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
curr_part_lba += 0x15E000;
|
||||
gpt_idx++;
|
||||
|
||||
// Android Misc partition.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x1800 - 1; // 3MB.
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'M', 0, 'S', 0, 'C', 0 }, 6);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + 0x1800 - 1; // 3MB.
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'M', 0, 'S', 0, 'C', 0 }, 6);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
curr_part_lba += 0x1800;
|
||||
gpt_idx++;
|
||||
@@ -416,12 +417,12 @@ static void _prepare_and_flash_mbr_gpt()
|
||||
u32 user_size = (part_info.and_size << 11) - 0x798000; // Subtract the other partitions (3888MB).
|
||||
if (!part_info.emu_size)
|
||||
user_size -= 0x800; // Reserve 1MB.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + user_size - 1;
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'U', 0, 'D', 0, 'A', 0 }, 6);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + user_size - 1;
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'U', 0, 'D', 0, 'A', 0 }, 6);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
curr_part_lba += user_size;
|
||||
gpt_idx++;
|
||||
@@ -429,51 +430,53 @@ static void _prepare_and_flash_mbr_gpt()
|
||||
if (part_info.emu_size)
|
||||
{
|
||||
u8 emu_part_guid[] = { 0x00, 0x7E, 0xCA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'e', 'm', 'u', 'M', 'M', 'C' };
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, emu_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, emu_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
if (!part_info.emu_double)
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 11) - 0x800 - 1; // Reserve 1MB.
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 11) - 0x800 - 1; // Reserve 1MB.
|
||||
else
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 10) - 1;
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'e', 0, 'm', 0, 'u', 0, 'm', 0, 'm', 0, 'c', 0 }, 12);
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 10) - 1;
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'e', 0, 'm', 0, 'u', 0, 'm', 0, 'm', 0, 'c', 0 }, 12);
|
||||
gpt_idx++;
|
||||
|
||||
if (part_info.emu_double)
|
||||
{
|
||||
curr_part_lba += (part_info.emu_size << 10);
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, emu_part_guid, 16);
|
||||
memcpy(gpt->entries[gpt_idx].type_guid, emu_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 10) - 0x800 - 1; // Reserve 1MB.
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'e', 0, 'm', 0, 'u', 0, 'm', 0, 'm', 0, 'c', 0, '2', 0 }, 14);
|
||||
memcpy(gpt->entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt->entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt->entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 10) - 0x800 - 1; // Reserve 1MB.
|
||||
memcpy(gpt->entries[gpt_idx].name, (char[]) { 'e', 0, 'm', 0, 'u', 0, 'm', 0, 'm', 0, 'c', 0, '2', 0 }, 14);
|
||||
gpt_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
// Set final GPT header parameters.
|
||||
gpt.header.num_part_ents = 128;
|
||||
gpt.header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt.entries, sizeof(gpt_entry_t) * 128);
|
||||
gpt.header.crc32 = 0; // Set to 0 for calculation.
|
||||
gpt.header.crc32 = crc32_calc(0, (const u8 *)&gpt.header, gpt.header.size);
|
||||
gpt->header.num_part_ents = 128;
|
||||
gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, sizeof(gpt_entry_t) * 128);
|
||||
gpt->header.crc32 = 0; // Set to 0 for calculation.
|
||||
gpt->header.crc32 = crc32_calc(0, (const u8 *)&gpt->header, gpt->header.size);
|
||||
|
||||
memcpy(&gpt_hdr_backup, &gpt.header, sizeof(gpt_header_t));
|
||||
memcpy(&gpt_hdr_backup, &gpt->header, sizeof(gpt_header_t));
|
||||
gpt_hdr_backup.my_lba = sd_storage.sec_cnt - 1;
|
||||
gpt_hdr_backup.alt_lba = 1;
|
||||
gpt_hdr_backup.part_ent_lba = sd_storage.sec_cnt - 33;
|
||||
gpt_hdr_backup.crc32 = 0; // Set to 0 for calculation.
|
||||
gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size);
|
||||
|
||||
// Write main GPT.
|
||||
sdmmc_storage_write(&sd_storage, gpt.header.my_lba, sizeof(gpt_t) >> 9, &gpt);
|
||||
// Write main gpt.
|
||||
sdmmc_storage_write(&sd_storage, gpt->header.my_lba, sizeof(gpt_t) >> 9, gpt);
|
||||
|
||||
// Write backup GPT partition table.
|
||||
sdmmc_storage_write(&sd_storage, gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt.entries);
|
||||
sdmmc_storage_write(&sd_storage, gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt->entries);
|
||||
|
||||
// Write backup GPT header.
|
||||
sdmmc_storage_write(&sd_storage, gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup);
|
||||
|
||||
free(gpt);
|
||||
}
|
||||
|
||||
// Write MBR.
|
||||
@@ -735,7 +738,7 @@ exit:
|
||||
static u32 _get_available_l4t_partition()
|
||||
{
|
||||
mbr_t mbr = { 0 };
|
||||
gpt_t gpt = { 0 };
|
||||
gpt_t *gpt = calloc(1, sizeof(gpt_t));
|
||||
|
||||
memset(&l4t_flash_ctxt, 0, sizeof(l4t_flasher_ctxt_t));
|
||||
|
||||
@@ -743,18 +746,18 @@ static u32 _get_available_l4t_partition()
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, &mbr);
|
||||
|
||||
// Read main GPT.
|
||||
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, &gpt);
|
||||
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, gpt);
|
||||
|
||||
// Search for a suitable partition.
|
||||
u32 size_sct = 0;
|
||||
if (!memcmp(&gpt.header.signature, "EFI PART", 8))
|
||||
if (!memcmp(&gpt->header.signature, "EFI PART", 8) || gpt->header.num_part_ents > 128)
|
||||
{
|
||||
for (u32 i = 0; i < gpt.header.num_part_ents; i++)
|
||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||
{
|
||||
if (!memcmp(gpt.entries[i].name, (char[]) { 'l', 0, '4', 0, 't', 0 }, 6))
|
||||
if (!memcmp(gpt->entries[i].name, (char[]) { 'l', 0, '4', 0, 't', 0 }, 6))
|
||||
{
|
||||
l4t_flash_ctxt.offset_sct = gpt.entries[i].lba_start;
|
||||
size_sct = (gpt.entries[i].lba_end + 1) - gpt.entries[i].lba_start;
|
||||
l4t_flash_ctxt.offset_sct = gpt->entries[i].lba_start;
|
||||
size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -775,30 +778,39 @@ static u32 _get_available_l4t_partition()
|
||||
}
|
||||
}
|
||||
|
||||
free(gpt);
|
||||
|
||||
return size_sct;
|
||||
}
|
||||
|
||||
static bool _get_available_android_partition()
|
||||
{
|
||||
gpt_t gpt = { 0 };
|
||||
gpt_t *gpt = calloc(1, sizeof(gpt_t));
|
||||
|
||||
// Read main GPT.
|
||||
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, &gpt);
|
||||
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, gpt);
|
||||
|
||||
// Check if GPT.
|
||||
if (memcmp(&gpt.header.signature, "EFI PART", 8))
|
||||
return false;
|
||||
if (memcmp(&gpt->header.signature, "EFI PART", 8) || gpt->header.num_part_ents > 128)
|
||||
goto out;
|
||||
|
||||
// Find kernel partition.
|
||||
for (u32 i = 0; i < gpt.header.num_part_ents; i++)
|
||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||
{
|
||||
if (gpt.entries[i].lba_start && !memcmp(gpt.entries[i].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6))
|
||||
if (gpt->entries[i].lba_start && !memcmp(gpt->entries[i].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6))
|
||||
{
|
||||
free(gpt);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i > 126)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
free(gpt);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -956,7 +968,7 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
|
||||
if (!btn_idx)
|
||||
{
|
||||
char path[128];
|
||||
gpt_t gpt = { 0 };
|
||||
gpt_t *gpt = calloc(1, sizeof(gpt_t));
|
||||
char *txt_buf = malloc(0x1000);
|
||||
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
@@ -983,10 +995,10 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
|
||||
sd_mount();
|
||||
|
||||
// Read main GPT.
|
||||
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, &gpt);
|
||||
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, gpt);
|
||||
|
||||
bool boot_twrp = false;
|
||||
if (memcmp(&gpt.header.signature, "EFI PART", 8))
|
||||
if (memcmp(&gpt->header.signature, "EFI PART", 8) || gpt->header.num_part_ents > 128)
|
||||
{
|
||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# No Android GPT was found!");
|
||||
goto error;
|
||||
@@ -997,12 +1009,12 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
|
||||
{
|
||||
u32 offset_sct = 0;
|
||||
u32 size_sct = 0;
|
||||
for (u32 i = 0; i < gpt.header.num_part_ents; i++)
|
||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||
{
|
||||
if (!memcmp(gpt.entries[i].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6))
|
||||
if (!memcmp(gpt->entries[i].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6))
|
||||
{
|
||||
offset_sct = gpt.entries[i].lba_start;
|
||||
size_sct = (gpt.entries[i].lba_end + 1) - gpt.entries[i].lba_start;
|
||||
offset_sct = gpt->entries[i].lba_start;
|
||||
size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1050,12 +1062,12 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
|
||||
{
|
||||
u32 offset_sct = 0;
|
||||
u32 size_sct = 0;
|
||||
for (u32 i = 0; i < gpt.header.num_part_ents; i++)
|
||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||
{
|
||||
if (!memcmp(gpt.entries[i].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6))
|
||||
if (!memcmp(gpt->entries[i].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6))
|
||||
{
|
||||
offset_sct = gpt.entries[i].lba_start;
|
||||
size_sct = (gpt.entries[i].lba_end + 1) - gpt.entries[i].lba_start;
|
||||
offset_sct = gpt->entries[i].lba_start;
|
||||
size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1102,12 +1114,12 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
|
||||
{
|
||||
u32 offset_sct = 0;
|
||||
u32 size_sct = 0;
|
||||
for (u32 i = 0; i < gpt.header.num_part_ents; i++)
|
||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||
{
|
||||
if (!memcmp(gpt.entries[i].name, (char[]) { 'D', 0, 'T', 0, 'B', 0 }, 6))
|
||||
if (!memcmp(gpt->entries[i].name, (char[]) { 'D', 0, 'T', 0, 'B', 0 }, 6))
|
||||
{
|
||||
offset_sct = gpt.entries[i].lba_start;
|
||||
size_sct = (gpt.entries[i].lba_end + 1) - gpt.entries[i].lba_start;
|
||||
offset_sct = gpt->entries[i].lba_start;
|
||||
size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1149,12 +1161,12 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
|
||||
lv_label_set_text(lbl_status, txt_buf);
|
||||
|
||||
// Check if TWRP is flashed unconditionally.
|
||||
for (u32 i = 0; i < gpt.header.num_part_ents; i++)
|
||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||
{
|
||||
if (!memcmp(gpt.entries[i].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6))
|
||||
if (!memcmp(gpt->entries[i].name, (char[]) { 'S', 0, 'O', 0, 'S', 0 }, 6))
|
||||
{
|
||||
u8 *buf = malloc(512);
|
||||
sdmmc_storage_read(&sd_storage, gpt.entries[i].lba_start, 1, buf);
|
||||
sdmmc_storage_read(&sd_storage, gpt->entries[i].lba_start, 1, buf);
|
||||
if (!memcmp(buf, "ANDROID", 7))
|
||||
boot_twrp = true;
|
||||
free(buf);
|
||||
@@ -1178,6 +1190,7 @@ error:
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
|
||||
free(txt_buf);
|
||||
free(gpt);
|
||||
|
||||
sd_unmount();
|
||||
}
|
||||
@@ -1359,8 +1372,7 @@ static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn)
|
||||
u32 total_size = 0;
|
||||
|
||||
// Read current MBR.
|
||||
part_info.mbr_old = (mbr_t *)calloc(512, 1);
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, part_info.mbr_old);
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, &part_info.mbr_old);
|
||||
|
||||
lv_label_set_text(lbl_status, "#00DDFF Status:# Initializing Ramdisk...");
|
||||
lv_label_set_text(lbl_paths[0], "Please wait...");
|
||||
@@ -1621,9 +1633,16 @@ static lv_res_t _create_mbox_partitioning_next(lv_obj_t *btn)
|
||||
s_printf(txt_buf, "#FFDD00 Warning: This will partition the SD Card!#\n\n");
|
||||
|
||||
if (part_info.backup_possible)
|
||||
strcat(txt_buf, "#C7EA46 Your files will be backed up and restored!#\n#FFDD00Any other partition will be wiped!#");
|
||||
{
|
||||
strcat(txt_buf, "#C7EA46 Your files will be backed up and restored!#\n"
|
||||
"#FFDD00 Any other partition will be wiped!#");
|
||||
}
|
||||
else
|
||||
strcat(txt_buf, "#FFDD00 Your files will be wiped!#\n#FFDD00 Use USB UMS to copy them over!#");
|
||||
{
|
||||
strcat(txt_buf, "#FFDD00 Your files will be wiped!#\n"
|
||||
"#FFDD00 Any other partition will be also wiped!#\n"
|
||||
"#FFDD00 Use USB UMS to copy them over!#");
|
||||
}
|
||||
|
||||
lv_label_set_text(lbl_status, txt_buf);
|
||||
|
||||
@@ -1909,7 +1928,8 @@ static void create_mbox_check_files_total_size()
|
||||
else
|
||||
{
|
||||
lv_mbox_set_text(mbox,
|
||||
"#FFDD00 The SD Card cannot be backed up!#\n\n"
|
||||
"#FFDD00 The SD Card cannot be backed up!#\n"
|
||||
"#FFDD00 Any other partition will be also wiped!#\n\n"
|
||||
"You will be asked to back up your files later via UMS.");
|
||||
}
|
||||
|
||||
@@ -1921,7 +1941,7 @@ static void create_mbox_check_files_total_size()
|
||||
|
||||
lv_obj_t *lbl_part = lv_label_create(h1, NULL);
|
||||
lv_label_set_recolor(lbl_part, true);
|
||||
lv_label_set_text(lbl_part, "#00DDFF Current partition layout:#");
|
||||
lv_label_set_text(lbl_part, "#00DDFF Current MBR partition layout:#");
|
||||
|
||||
// Read current MBR.
|
||||
mbr_t mbr = { 0 };
|
||||
@@ -2030,53 +2050,66 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
|
||||
}
|
||||
|
||||
mbr_t mbr[2] = { 0 };
|
||||
gpt_t gpt = { 0 };
|
||||
gpt_t *gpt = calloc(1, sizeof(gpt_t));
|
||||
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, &mbr[0]);
|
||||
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, &gpt);
|
||||
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, gpt);
|
||||
|
||||
memcpy(&mbr[1], &mbr[0], sizeof(mbr_t));
|
||||
|
||||
sd_unmount();
|
||||
|
||||
if (memcmp(&gpt.header.signature, "EFI PART", 8))
|
||||
if (memcmp(&gpt->header.signature, "EFI PART", 8) || gpt->header.num_part_ents > 128)
|
||||
{
|
||||
lv_label_set_text(lbl_status, "#FFDD00 Warning:# No GPT was found!");
|
||||
lv_label_set_text(lbl_status, "#FFDD00 Warning:# No valid GPT was found!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Parse GPT.
|
||||
LIST_INIT(gpt_parsed);
|
||||
for (u32 i = 0; i < gpt.header.num_part_ents; i++)
|
||||
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
|
||||
{
|
||||
emmc_part_t *part = (emmc_part_t *)calloc(sizeof(emmc_part_t), 1);
|
||||
|
||||
if (gpt.entries[i].lba_start < gpt.header.first_use_lba)
|
||||
if (gpt->entries[i].lba_start < gpt->header.first_use_lba)
|
||||
continue;
|
||||
|
||||
part->index = i;
|
||||
part->lba_start = gpt.entries[i].lba_start;
|
||||
part->lba_end = gpt.entries[i].lba_end;
|
||||
part->attrs = gpt.entries[i].attrs;
|
||||
part->lba_start = gpt->entries[i].lba_start;
|
||||
part->lba_end = gpt->entries[i].lba_end;
|
||||
|
||||
// ASCII conversion. Copy only the LSByte of the UTF-16LE name.
|
||||
for (u32 j = 0; j < 36; j++)
|
||||
part->name[j] = gpt.entries[i].name[j];
|
||||
part->name[j] = gpt->entries[i].name[j];
|
||||
part->name[35] = 0;
|
||||
|
||||
list_append(&gpt_parsed, &part->link);
|
||||
}
|
||||
free(gpt);
|
||||
|
||||
u32 mbr_idx = 0;
|
||||
// Set FAT and emuMMC partitions.
|
||||
u32 mbr_idx = 1;
|
||||
bool found_hos_data = false;
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt_parsed, link)
|
||||
{
|
||||
if (!strcmp(part->name, "hos_data"))
|
||||
// FatFS simple GPT found a fat partition, set it.
|
||||
if (sd_fs.part_type && !part->index)
|
||||
{
|
||||
mbr[1].partitions[mbr_idx].type = sd_fs.fs_type == FS_EXFAT ? 0x7 : 0xC;
|
||||
mbr[1].partitions[mbr_idx].start_sct = part->lba_start;
|
||||
mbr[1].partitions[mbr_idx].size_sct = (part->lba_end - part->lba_start + 1);
|
||||
mbr_idx++;
|
||||
mbr[1].partitions[0].type = sd_fs.fs_type == FS_EXFAT ? 0x7 : 0xC;
|
||||
mbr[1].partitions[0].start_sct = part->lba_start;
|
||||
mbr[1].partitions[0].size_sct = (part->lba_end - part->lba_start + 1);
|
||||
}
|
||||
|
||||
// FatFS simple GPT didn't find a fat partition as the first one.
|
||||
if (!sd_fs.part_type && !found_hos_data && !strcmp(part->name, "hos_data"))
|
||||
{
|
||||
mbr[1].partitions[0].type = 0xC;
|
||||
mbr[1].partitions[0].start_sct = part->lba_start;
|
||||
mbr[1].partitions[0].size_sct = (part->lba_end - part->lba_start + 1);
|
||||
found_hos_data = true;
|
||||
}
|
||||
|
||||
// Set up to max 2 emuMMC partitions.
|
||||
if (!strcmp(part->name, "emummc") || !strcmp(part->name, "emummc2"))
|
||||
{
|
||||
mbr[1].partitions[mbr_idx].type = 0xE0;
|
||||
@@ -2085,11 +2118,15 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
|
||||
mbr_idx++;
|
||||
}
|
||||
|
||||
if (mbr_idx > 2)
|
||||
// Total reached last slot.
|
||||
if (mbr_idx >= 3)
|
||||
break;
|
||||
}
|
||||
|
||||
mbr[1].partitions[mbr_idx].type = 0xEE; // GPT protective partition.
|
||||
nx_emmc_gpt_free(&gpt_parsed);
|
||||
|
||||
// Set GPT protective partition.
|
||||
mbr[1].partitions[mbr_idx].type = 0xEE;
|
||||
mbr[1].partitions[mbr_idx].start_sct = 1;
|
||||
mbr[1].partitions[mbr_idx].size_sct = sd_storage.sec_cnt - 1;
|
||||
|
||||
|
||||
@@ -207,6 +207,21 @@ void gfx_putc(char c)
|
||||
cbuf++;
|
||||
}
|
||||
gfx_con.x += 16;
|
||||
if (gfx_con.x > gfx_ctxt.width - 16)
|
||||
{
|
||||
gfx_con.x = gfx_column;
|
||||
gfx_con.y += 16;
|
||||
if (gfx_con.y > gfx_ctxt.height - 33)
|
||||
{
|
||||
gfx_con.y = 0;
|
||||
|
||||
if (!gfx_column)
|
||||
gfx_column = 640;
|
||||
else
|
||||
gfx_column = 0;
|
||||
gfx_con.x = gfx_column;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
@@ -243,6 +258,21 @@ void gfx_putc(char c)
|
||||
}
|
||||
}
|
||||
gfx_con.x += 8;
|
||||
if (gfx_con.x > gfx_ctxt.width / 2 + gfx_column - 8)
|
||||
{
|
||||
gfx_con.x = gfx_column;
|
||||
gfx_con.y += 8;
|
||||
if (gfx_con.y > gfx_ctxt.height - 33)
|
||||
{
|
||||
gfx_con.y = 0;
|
||||
|
||||
if (!gfx_column)
|
||||
gfx_column = 640;
|
||||
else
|
||||
gfx_column = 0;
|
||||
gfx_con.x = gfx_column;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
|
||||
@@ -57,7 +57,8 @@ static const pkg1_id_t _pkg1_ids[] = {
|
||||
{ "20190809135709", 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.0.0 - 9.0.1.
|
||||
{ "20191021113848", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.1.0 - 9.2.0.
|
||||
{ "20200303104606", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 10.0.0 - 10.2.0.
|
||||
{ "20201030110855", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 11.0.0+
|
||||
{ "20201030110855", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 11.0.0 - 11.0.1
|
||||
{ "20210129111626", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 12.0.0+
|
||||
{ NULL } //End.
|
||||
};
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
|
||||
|
||||
sdmmc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf);
|
||||
|
||||
// Check if no GPT or more than max allowed entries.
|
||||
if (memcmp(&gpt_buf->header.signature, "EFI PART", 8) || gpt_buf->header.num_part_ents > 128)
|
||||
goto out;
|
||||
|
||||
for (u32 i = 0; i < gpt_buf->header.num_part_ents; i++)
|
||||
{
|
||||
emmc_part_t *part = (emmc_part_t *)calloc(sizeof(emmc_part_t), 1);
|
||||
@@ -53,6 +57,7 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
|
||||
list_append(gpt, &part->link);
|
||||
}
|
||||
|
||||
out:
|
||||
free(gpt_buf);
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool flush
|
||||
if (!emu_offset)
|
||||
res = nx_emmc_part_write(&emmc_storage, system_part, sector, count, bis_cache->dma_buff);
|
||||
else
|
||||
res = sdmmc_storage_read(&sd_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
|
||||
res = sdmmc_storage_write(&sd_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
|
||||
if (!res)
|
||||
return 1; // R/W error.
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -34,32 +33,39 @@ main ( int argc, char* argv[] )
|
||||
{
|
||||
unsigned char buf[BUFSIZ];
|
||||
char* ident;
|
||||
int fd, i, total, rd, need_comma;
|
||||
FILE *fd;
|
||||
size_t size, i, total, blksize = BUFSIZ;
|
||||
int need_comma = 0;
|
||||
|
||||
if ( argc < 2 )
|
||||
if ( argc != 2 )
|
||||
{
|
||||
fprintf ( stderr, "Usage: %s binary_file > output_file\n", argv[0] );
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open ( argv[1], O_RDONLY );
|
||||
if ( fd == -1 )
|
||||
fd = fopen ( argv[1], "rb" );
|
||||
if ( fd == NULL )
|
||||
{
|
||||
fprintf ( stderr, "%s: can't open %s for reading\n", argv[0], argv[1] );
|
||||
return -1;
|
||||
}
|
||||
|
||||
fseek(fd, 0, SEEK_END);
|
||||
size = ftell(fd);
|
||||
rewind(fd);
|
||||
|
||||
ident = make_ident ( argv[1] );
|
||||
|
||||
printf ( "static const unsigned char __attribute__((section (\"._%s\"))) %s[] = {", ident, ident );
|
||||
for ( total = 0, need_comma = 0; ( rd = read ( fd, buf, BUFSIZ ) ) != 0; )
|
||||
for ( total = 0; total < size; )
|
||||
{
|
||||
if ( rd == -1 )
|
||||
if ( size - total < blksize ) blksize = size - total;
|
||||
if ( fread ( buf, 1, blksize, fd ) != blksize )
|
||||
{
|
||||
fprintf ( stderr, "%s: file read error\n", argv[0] );
|
||||
return -1;
|
||||
}
|
||||
for ( i = 0; i < rd; i++ )
|
||||
for ( i = 0; i < blksize; i++ )
|
||||
{
|
||||
if ( need_comma ) printf ( ", " );
|
||||
else need_comma = 1;
|
||||
@@ -70,7 +76,7 @@ main ( int argc, char* argv[] )
|
||||
}
|
||||
printf ( "\n};\n" );
|
||||
|
||||
close ( fd );
|
||||
fclose ( fd );
|
||||
free ( ident );
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user