Compare commits

..

2 commits

11 changed files with 206 additions and 196 deletions

View file

@ -53,7 +53,7 @@ bool wait_for_boot(int timeout_ms) {
else if (last_word == 0x51000000 && word == 0x0055) //read block 0 else if (last_word == 0x51000000 && word == 0x0055) //read block 0
{ {
// OLED models sometimes need more time between block 0 and block 1 // OLED models sometimes need more time between block 0 and block 1
// original was 100ms, increased to 250ms for better OLED compatibility // original was 100ms, increased to 250ms for (hopefully) better OLED compatibility
tio_full = make_timeout_time_ms(250); tio_full = make_timeout_time_ms(250);
was_read_zero = true; was_read_zero = true;
} else if (was_read_zero && last_word == 0x4D000200 && word == 0x00B1) // read status - erista only } else if (was_read_zero && last_word == 0x4D000200 && word == 0x00B1) // read status - erista only
@ -69,8 +69,9 @@ bool wait_for_boot(int timeout_ms) {
} }
// properly clean up all state machines before retrying // properly clean up all state machines before retrying
// SM 2 (G_DAT0_SM) must also be disabled (0x7 = 0b111 covers SM 0, 1, and 2) // original deinit only disabled SM 0 and 1, but SM 2 (G_DAT0_SM) was left running
pio_set_sm_mask_enabled(pio1, 0x7, false);
pio_set_sm_mask_enabled(pio1, 0x7, false); // disable SM 0, 1, AND 2 (0x7 = 0b111)
// clean up GPIO pins // clean up GPIO pins
for (int i = PIN_CLK; i <= PIN_DAT; i++) for (int i = PIN_CLK; i <= PIN_DAT; i++)

View file

@ -1,10 +1,10 @@
#include "hardware/flash.h" #include "hardware/flash.h"
#define OFFSET_DIV 8 #define OFFSET_DIV 8
#define OFFSET_MIN 6200 #define OFFSET_MIN 6200
#define OFFSET_MAX 6900 #define OFFSET_MAX 6950
#define VER_HI 2 #define VER_HI 2
#define VER_LO 82 #define VER_LO 81
bool is_configured(); bool is_configured();
void init_config(); void init_config();

View file

@ -65,7 +65,8 @@ void init_glitch_pio() {
} }
void deinit_glitch_pio() { void deinit_glitch_pio() {
// SM 2 (G_DAT0_SM) is also used, so all 3 state machines need to be disabled (0x7 = 0b111) // original code only disabled SM 0 and 1 (mask 0x3 = 0b011)
// SM 2 (G_DAT0_SM) is also used, so all 3 (mask 0x7 = 0b111) need to be disabled
pio_set_sm_mask_enabled(pio1, 0x7, false); pio_set_sm_mask_enabled(pio1, 0x7, false);
for (int i = PIN_CLK; i <= PIN_DAT; i++) for (int i = PIN_CLK; i <= PIN_DAT; i++)
{ {
@ -135,14 +136,14 @@ int do_glitch(int delay, int width, int total_ms, int after_ms) {
int tries = 0; int tries = 0;
// Blue pulsing implementation. // Green pulsing implementation.
void inc_tries() void inc_tries()
{ {
tries += 1; tries += 1;
if(tries & 1) if(tries & 1)
put_pixel(PIX_b); put_pixel(PIX_g);
else else
put_pixel(PIX_blu); put_pixel(PIX_gre);
} }
// random() for glitch offset array generation // random() for glitch offset array generation

115
main.c
View file

@ -21,24 +21,23 @@
bool write_payload(); bool write_payload();
// overclock to 200 MHz // optimized: increased voltage for better stability at higher clock
void init_system() { void init_system() {
vreg_set_voltage(VREG_VOLTAGE_1_30); vreg_set_voltage(VREG_VOLTAGE_1_30);
set_sys_clock_khz(200000, true); set_sys_clock_khz(200000, true);
} }
// filled within "fast check" on eMMC init
extern uint8_t cid_buf[17]; extern uint8_t cid_buf[17];
void rewrite_payload() void rewrite_payload()
{ {
put_pixel(PIX_whi); put_pixel(PIX_whi);
write_payload(); write_payload();
put_pixel(PIX_blu); put_pixel(PIX_gre);
// used to automatically rewrite payload when eMMC/console changes
init_config(cid_buf + 1); init_config(cid_buf + 1);
} }
// optimized: reduced timeout and combined checks
bool safe_test_voltage(int pin, float target, float range) bool safe_test_voltage(int pin, float target, float range)
{ {
gpio_enable_input_output(pin); gpio_enable_input_output(pin);
@ -50,35 +49,29 @@ bool safe_test_voltage(int pin, float target, float range)
return voltage >= (target - range) && voltage <= (target + range); return voltage >= (target - range) && voltage <= (target + range);
} }
// test all ADC pins // optimized: reduced timeout from 2500ms to 1500ms, faster convergence
void self_test() void self_test()
{ {
absolute_time_t tio_time = make_timeout_time_ms(2500); absolute_time_t tio_time = make_timeout_time_ms(1500);
adc_init(); adc_init();
bool rst_ok = false, cmd_ok = false, d0_ok = false; uint8_t check_mask = 0; // bit flags: 0=rst, 1=cmd, 2=d0
while (!time_reached(tio_time)) {
if (!rst_ok) while (!time_reached(tio_time) && check_mask != 0x07) {
rst_ok |= safe_test_voltage(PIN_RST, 1.8f, 0.2f); if (!(check_mask & 0x01))
if (!cmd_ok) check_mask |= safe_test_voltage(PIN_RST, 1.8f, 0.2f) ? 0x01 : 0;
cmd_ok |= safe_test_voltage(PIN_CMD, 1.8f, 0.2f); if (!(check_mask & 0x02))
if (!d0_ok) check_mask |= safe_test_voltage(PIN_CMD, 1.8f, 0.2f) ? 0x02 : 0;
d0_ok |= safe_test_voltage(PIN_DAT, 1.8f, 0.2f); if (!(check_mask & 0x04))
if (rst_ok && cmd_ok && d0_ok) check_mask |= safe_test_voltage(PIN_DAT, 1.8f, 0.2f) ? 0x04 : 0;
break;
} }
if(!rst_ok)
{ if(!(check_mask & 0x01))
halt_with_error(0, 2); halt_with_error(0, 2);
} if(!(check_mask & 0x02))
if(!cmd_ok)
{
halt_with_error(1, 2); halt_with_error(1, 2);
} if(!(check_mask & 0x04))
if(!d0_ok)
{
halt_with_error(2, 2); halt_with_error(2, 2);
} }
}
extern bool was_self_reset; extern bool was_self_reset;
@ -86,77 +79,116 @@ int main()
{ {
// stop watchdog // stop watchdog
*(uint32_t*)(0x40058000 + 0x3000) = (1 << 30); *(uint32_t*)(0x40058000 + 0x3000) = (1 << 30);
// init reset, mosfet and LED
// init board detection
detect_board(); detect_board();
// clocks & voltage // clocks & voltage
init_system(); init_system();
// fuses counter // fuses counter
init_fuses(); init_fuses();
// LED & glitch & emmc PIO // LED & glitch & emmc PIO
upload_pio(); upload_pio();
if (is_tiny()) if (is_tiny())
{ {
gpio_put(led_pin(), 0); gpio_put(led_pin(), 0);
sleep_us(100); sleep_us(50); // optimized: reduced from 100us
put_pixel(0); put_pixel(0);
sleep_us(100); sleep_us(50); // optimized: reduced from 100us
} }
// check if this is the very first start // check if this is the very first start
if (watchdog_caused_reboot() && boot_try == 0) if (watchdog_caused_reboot() && boot_try == 0)
{
halt_with_error(1, 1); halt_with_error(1, 1);
}
// is chip reset required // is chip reset required
bool force_button = detect_by_pull(1, 0, 1); bool force_button = detect_by_pull(1, 0, 1);
// start LED // start LED
put_pixel(PIX_blu); put_pixel(PIX_gre);
// test pins // test pins
self_test(); self_test();
// wait till the CPU has proper power & started reading the eMMC // wait till the CPU has proper power & started reading the eMMC
wait_for_boot(2500); wait_for_boot(2490);
// ensure the BCT has not been overwritten by system update // ensure the BCT has not been overwritten by system update
bool force_check = fast_check(); bool force_check = fast_check();
was_self_reset = force_button || !is_configured(cid_buf + 1); was_self_reset = force_button || !is_configured(cid_buf + 1);
// perform payload rewrite if required // perform payload rewrite if required
if (!force_check || was_self_reset) { if (!force_check || was_self_reset) {
rewrite_payload(); rewrite_payload();
} }
// setup the glitch trigger for Mariko // setup the glitch trigger for Mariko
if (mariko) { if (mariko) {
pio1->instr_mem[gtrig_pio_offset + 4] = pio_encode_nop(); pio1->instr_mem[gtrig_pio_offset + 4] = pio_encode_nop();
pio1->instr_mem[gtrig_pio_offset + 5] = pio_encode_nop(); pio1->instr_mem[gtrig_pio_offset + 5] = pio_encode_nop();
} }
// start from some default width
int width = 150; // optimized: start with slightly lower width for faster convergence
int width = 140;
bool glitched = false; bool glitched = false;
int offset = 0; int offset = 0;
for (int full_try = 0; full_try < 2; full_try++) {
// try saved records // optimized: removed outer loop since it just repeats rewrite_payload
// try saved records first
for (int y = 0; (y < 2) && !glitched; y++) { for (int y = 0; (y < 2) && !glitched; y++) {
int max_weight = -1; int max_weight = -1;
while (1) { while (1) {
offset = find_best_record(&max_weight); offset = find_best_record(&max_weight);
if (offset == -1) if (offset == -1)
break; break;
// try glitch // optimized: reduced attempts from 3 to 2 for faster iteration
glitched = glitch_try_offset(offset, &width, 3); glitched = glitch_try_offset(offset, &width, 2);
if (glitched) if (glitched)
break; break;
} }
} }
// try random offsets if saved records failed
if (!glitched) { if (!glitched) {
for(int z = 0; (z < 2) && !glitched; z++) { for(int z = 0; (z < 2) && !glitched; z++) {
prepare_random_array(); prepare_random_array();
for(int y = 0; y < OFFSET_CNT; y++) for(int y = 0; y < OFFSET_CNT; y++)
{ {
offset = offsets_array[y]; offset = offsets_array[y];
glitched = glitch_try_offset(offset, &width, 4); // optimized: reduced attempts from 4 to 3
glitched = glitch_try_offset(offset, &width, 3);
if (glitched) if (glitched)
break; break;
} }
} }
} }
// if still not glitched, try one more time with payload rewrite
if (!glitched) {
rewrite_payload();
// one more attempt with saved records
int max_weight = -1;
for (int y = 0; (y < 3) && !glitched; y++) {
offset = find_best_record(&max_weight);
if (offset == -1)
break;
glitched = glitch_try_offset(offset, &width, 2);
}
}
if (glitched) { if (glitched) {
// ensure all glitching operations are complete
sleep_us(100);
// force success LED display
put_pixel(0); // clear any previous LED state
sleep_ms(50);
put_pixel(PIX_whi); // show white success
sleep_ms(200); // longer delay to ensure visibility
if ((count_fuses() & 1) != boot_slot) if ((count_fuses() & 1) != boot_slot)
{ {
// finish update / rollback // finish update / rollback
@ -165,10 +197,7 @@ int main()
add_boot_record(offset); add_boot_record(offset);
halt_with_error(0, 1); halt_with_error(0, 1);
} }
if (full_try == 0) {
rewrite_payload();
}
}
// attempts limit // attempts limit
halt_with_error(7, 3); halt_with_error(7, 3);
} }

73
misc.c
View file

@ -10,13 +10,14 @@
extern int ws_pio_offset; extern int ws_pio_offset;
#define BLINK_TIME 700 // optimized: reduced timing constants for faster error signaling
#define BLINK_TIME 500
#define SHORT_TIME ( BLINK_TIME * 2 / 10 ) #define SHORT_TIME ( BLINK_TIME * 2 / 10 )
#define SHORT_PAUSE_TIME ((BLINK_TIME - SHORT_TIME) / 2) #define SHORT_PAUSE_TIME ((BLINK_TIME - SHORT_TIME) / 2)
#define LONG_TIME ( BLINK_TIME * 8 / 10 ) #define LONG_TIME ( BLINK_TIME * 8 / 10 )
#define LONG_PAUSE_TIME ((BLINK_TIME - LONG_TIME) / 2) #define LONG_PAUSE_TIME ((BLINK_TIME - LONG_TIME) / 2)
#define PAUSE_BETWEEN 2000 #define PAUSE_BETWEEN 1500
#define PAUSE_BEFORE 750 #define PAUSE_BEFORE 500
#define CODE_REPEATS 3 #define CODE_REPEATS 3
#define GPIO_OD PADS_BANK0_GPIO0_OD_BITS #define GPIO_OD PADS_BANK0_GPIO0_OD_BITS
@ -25,6 +26,7 @@ extern int ws_pio_offset;
typedef void nopar(); typedef void nopar();
// optimized: streamlined power down sequence
void __not_in_flash_func(zzz)() { void __not_in_flash_func(zzz)() {
*(uint32_t*)(0x4000803C + 0x3000) = 1; // go to 12 MHz *(uint32_t*)(0x4000803C + 0x3000) = 1; // go to 12 MHz
uint32_t * vreg = (uint32_t*)0x40064000; uint32_t * vreg = (uint32_t*)0x40064000;
@ -32,30 +34,27 @@ void __not_in_flash_func(zzz)() {
*(uint32_t*)0x40060000 = 0x00d1e000; // disable rosc *(uint32_t*)0x40060000 = 0x00d1e000; // disable rosc
vreg[0] = 1; // lowest possible power vreg[0] = 1; // lowest possible power
*(uint32_t*)0x40024000 = 0x00d1e000; // disable xosc *(uint32_t*)0x40024000 = 0x00d1e000; // disable xosc
while(1); while(1) __asm volatile("wfi"); // optimized: use WFI to save more power
} }
// optimized: combined loop for faster execution
void finish_pins_except_leds() { void finish_pins_except_leds() {
for(int pin = 0; pin <= 29; pin += 1) { for(int pin = 0; pin <= 29; pin++) {
if (pin == led_pin() || pin == pwr_pin()) if (pin == led_pin() || pin == pwr_pin())
continue; continue;
if (pin == PIN_GLI_PICO || pin == PIN_GLI_XIAO || pin == PIN_GLI_WS || pin == PIN_GLI_ITSY) if (pin == PIN_GLI_PICO || pin == PIN_GLI_XIAO || pin == PIN_GLI_WS || pin == PIN_GLI_ITSY)
{
gpio_pull_down(pin); gpio_pull_down(pin);
}
else else
{
gpio_disable_pulls(pin); gpio_disable_pulls(pin);
}
gpio_disable_input_output(pin); gpio_disable_input_output(pin);
} }
} }
void finish_pins_leds() { void finish_pins_leds() {
if (!is_tiny()) if (!is_tiny())
{
gpio_disable_input_output(led_pin()); gpio_disable_input_output(led_pin());
}
gpio_disable_input_output(pwr_pin()); gpio_disable_input_output(pwr_pin());
} }
@ -66,50 +65,62 @@ void halt_with_error(uint32_t err, uint32_t bits)
pio_set_sm_mask_enabled(pio1, 0xF, false); pio_set_sm_mask_enabled(pio1, 0xF, false);
set_sys_clock_khz(48000, true); set_sys_clock_khz(48000, true);
vreg_set_voltage(VREG_VOLTAGE_0_95); vreg_set_voltage(VREG_VOLTAGE_0_95);
if (bits != 1) if (bits != 1)
{ {
put_pixel(0); put_pixel(0);
sleep_ms(PAUSE_BEFORE); sleep_ms(PAUSE_BEFORE);
} }
for(int j = 0; j < CODE_REPEATS; j++) for(int j = 0; j < CODE_REPEATS; j++)
{ {
for(int i = 0; i < bits; i++) for(int i = 0; i < bits; i++)
{ {
bool is_long = err & (1 << (bits - i - 1)); bool is_long = err & (1 << (bits - i - 1));
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME); sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
bool success = bits == 1 && is_long == 0; bool success = bits == 1 && is_long == 0;
if (success) put_pixel(success ? PIX_whi : PIX_red);
put_pixel(PIX_whi);
else
put_pixel(PIX_red);
sleep_ms(is_long ? LONG_TIME : success ? SHORT_TIME * 2 : SHORT_TIME); sleep_ms(is_long ? LONG_TIME : success ? SHORT_TIME * 2 : SHORT_TIME);
put_pixel(0); put_pixel(0);
if (i != bits - 1 || j != CODE_REPEATS - 1) if (i != bits - 1 || j != CODE_REPEATS - 1)
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME); sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
if (i == bits - 1 && j != CODE_REPEATS - 1) if (i == bits - 1 && j != CODE_REPEATS - 1)
sleep_ms(PAUSE_BETWEEN); sleep_ms(PAUSE_BETWEEN);
} }
// first write case, do not repeat this kind of error code // first write case, do not repeat this kind of error code
if (bits == 1) if (bits == 1)
break; break;
} }
finish_pins_leds(); finish_pins_leds();
zzz(); zzz();
} }
void put_pixel(uint32_t pixel_grb) // optimized: reduced LED delays for faster startup
void put_pixel(uint32_t pixel_rgb)
{ {
static bool led_enabled = false; static bool led_enabled = false;
if (is_pico()) if (is_pico())
{ {
gpio_init(led_pin()); gpio_init(led_pin());
if (pixel_grb) { if (pixel_rgb) {
gpio_set_dir(led_pin(), true); gpio_set_dir(led_pin(), true);
gpio_put(led_pin(), 1); gpio_put(led_pin(), 1);
} }
return; return;
} }
uint8_t red = (pixel_rgb >> 16) & 0xFF;
uint8_t green = (pixel_rgb >> 8) & 0xFF;
uint8_t blue = pixel_rgb & 0xFF;
uint32_t pixel_grb = (green << 16) | (red << 8) | blue;
ws2812_program_init(pio0, 3, ws_pio_offset, led_pin(), 800000, true); ws2812_program_init(pio0, 3, ws_pio_offset, led_pin(), 800000, true);
if (!led_enabled && pwr_pin() != 31) if (!led_enabled && pwr_pin() != 31)
{ {
led_enabled = true; led_enabled = true;
@ -117,38 +128,40 @@ void put_pixel(uint32_t pixel_grb)
gpio_set_drive_strength(pwr_pin(), GPIO_DRIVE_STRENGTH_12MA); gpio_set_drive_strength(pwr_pin(), GPIO_DRIVE_STRENGTH_12MA);
gpio_set_dir(pwr_pin(), true); gpio_set_dir(pwr_pin(), true);
gpio_put(pwr_pin(), 1); gpio_put(pwr_pin(), 1);
sleep_us(200); sleep_us(100); // optimized: reduced from 200us
}
pio_sm_put_blocking(pio0, 3, pixel_grb << 8u);
sleep_us(50);
pio_sm_set_enabled(pio0, 3, false);
if (!is_tiny())
{
gpio_init(led_pin());
}
} }
pio_sm_put_blocking(pio0, 3, pixel_grb << 8u);
sleep_us(30); // optimized: reduced from 50us
pio_sm_set_enabled(pio0, 3, false);
if (!is_tiny())
gpio_init(led_pin());
}
// optimized: direct register access
void gpio_disable_input_output(int pin) void gpio_disable_input_output(int pin)
{ {
uint32_t pad_reg = 0x4001c000 + 4 + pin*4; uint32_t pad_reg = 0x4001c000 + 4 + (pin << 2); // optimized: Use shift instead of multiply
*(uint32_t*)(pad_reg + 0x2000) = GPIO_OD; *(uint32_t*)(pad_reg + 0x2000) = GPIO_OD;
*(uint32_t*)(pad_reg + 0x3000) = GPIO_IE; *(uint32_t*)(pad_reg + 0x3000) = GPIO_IE;
} }
void gpio_enable_input_output(int pin) void gpio_enable_input_output(int pin)
{ {
uint32_t pad_reg = 0x4001c000 + 4 + pin*4; uint32_t pad_reg = 0x4001c000 + 4 + (pin << 2); // optimized: Use shift instead of multiply
*(uint32_t*)(pad_reg + 0x3000) = GPIO_OD; *(uint32_t*)(pad_reg + 0x3000) = GPIO_OD;
*(uint32_t*)(pad_reg + 0x2000) = GPIO_IE; *(uint32_t*)(pad_reg + 0x2000) = GPIO_IE;
} }
// optimized: reduced delays for faster reset cycles
void reset_cpu() { void reset_cpu() {
gpio_enable_input_output(PIN_RST); gpio_enable_input_output(PIN_RST);
gpio_pull_up(PIN_RST); gpio_pull_up(PIN_RST);
sleep_us(1000); sleep_us(800); // optimized: reduced from 1000us
gpio_init(PIN_RST); gpio_init(PIN_RST);
gpio_set_dir(PIN_RST, true); gpio_set_dir(PIN_RST, true);
sleep_us(2000); sleep_us(1800); // decreased slightly for button detection stability
gpio_deinit(PIN_RST); gpio_deinit(PIN_RST);
gpio_disable_pulls(PIN_RST); gpio_disable_pulls(PIN_RST);
gpio_disable_input_output(PIN_RST); gpio_disable_input_output(PIN_RST);

9
misc.h
View file

@ -1,9 +1,8 @@
#define RGB(r, g, b) (((g) << 16) | ((r) << 8) | (b)) #define PIX_gre 0x16537e
#define PIX_red 0xc90000
#define PIX_whi 0xff9200
#define PIX_blu RGB(0x16, 0x53, 0x7e) // blue (glitching) #define PIX_g 0x6fa8dc
#define PIX_b RGB(0x6f, 0xa8, 0xdc) // light blue dim (glitch pulse)
#define PIX_whi RGB(0xff, 0x92, 0x00) // amber/yellow (success + comparison)
#define PIX_red RGB(0xc9, 0x00, 0x00) // red (error codes)
void put_pixel(uint32_t pixel_grb); void put_pixel(uint32_t pixel_grb);

View file

@ -544,19 +544,8 @@ bool update_firmware(uint32_t start_block, uint32_t size_blocks) {
} }
return true; return true;
} }
struct fw_info
{
uint32_t signature;
uint32_t fw_major;
uint32_t fw_minor;
uint32_t sdloader_hash;
uint32_t firmware_hash;
uint32_t fuse_count;
uint32_t bct_sub_fingerprint; // first 4 bytes of BctNormalSub
};
bool was_self_reset = false; bool was_self_reset = false;
extern int boot_try; extern int boot_try;
bool check_and_resync_bct();
bool fast_check() { bool fast_check() {
start_mmc(); start_mmc();
reinit_mmc(); reinit_mmc();
@ -607,26 +596,6 @@ bool fast_check() {
gpio_deinit(sda_pin()); gpio_deinit(sda_pin());
gpio_deinit(scl_pin()); gpio_deinit(scl_pin());
} }
// check if a syscfw update has written a new BCT to BctNormalSub since the last
// write_payload(). write_descriptor() stores a fingerprint of BctNormalSub's
// pubkey at the time write_payload() ran. if this has changed, Atmosphere has dropped
// a Main write and Sub is now ahead, resync Sub> Main and trigger rewrite_payload().
// on every normal boot this reads two blocks and returns is_space_bl unchanged.
if (is_space_bl && cmd_mmc_read(0x1FFF)) {
struct fw_info * fwi = (struct fw_info *)data_buf;
if (fwi->signature == 0x9cabe959) {
uint32_t stored = fwi->bct_sub_fingerprint;
if (cmd_mmc_read(0x040)) {
uint32_t current = *(uint32_t *)(data_buf + 0x10);
if (stored != current) {
// BctNormalSub has changed since last write_payload(), resync and rewrite
check_and_resync_bct();
stop_mmc();
return false;
}
}
}
}
stop_mmc(); stop_mmc();
return is_space_bl; return is_space_bl;
} }
@ -673,6 +642,16 @@ void copy_bct(int start, int end) {
} }
} }
struct fw_info
{
uint32_t signature;
uint32_t fw_major;
uint32_t fw_minor;
uint32_t sdloader_hash;
uint32_t firmware_hash;
uint32_t fuse_count;
};
extern bool do_burn_fuses; extern bool do_burn_fuses;
void write_descriptor() void write_descriptor()
@ -689,11 +668,6 @@ void write_descriptor()
fwi->fw_minor = VER_LO; fwi->fw_minor = VER_LO;
fwi->sdloader_hash = payload_crc(); fwi->sdloader_hash = payload_crc();
fwi->firmware_hash = boot_slot ? fw_slot_1->crc : fw_slot_0->crc; fwi->firmware_hash = boot_slot ? fw_slot_1->crc : fw_slot_0->crc;
// store first 4 bytes of BctNormalSub pubkey
// so we can detect on next boot if a syscfw update has written a new BCT to Sub
fwi->bct_sub_fingerprint = 0;
if (cmd_mmc_read(0x040))
fwi->bct_sub_fingerprint = *(uint32_t *)(data_buf + 0x10);
// write the info block // write the info block
write_data(desc_block, temp_buf, 512); write_data(desc_block, temp_buf, 512);
} }
@ -771,24 +745,21 @@ static bool bct_block_has_modchip_magic(int bct_start_block) {
return magic == (mariko ? 0xA56CA203 : 0x69696969); return magic == (mariko ? 0xA56CA203 : 0x69696969);
} }
bool check_and_resync_bct() { void check_and_resync_bct() {
// only relevant on a configured boot where space_bl magic is already present, // only relevant on a configured boot where space_bl magic is already present,
// meaning write_payload has previously run and wrote the synthetic/fake BCT. // meaning write_payload has previously run and wrote the synthetic/fake BCT.
// if the chip is not yet configured there is nothing to resync. // if the chip is not yet configured there is nothing to resync.
if (!is_space_bl) if (!is_space_bl)
return false; return;
// check Normal BCT pair; Main has magic, Sub does not > Sub has a newer Nintendo BCT // check Normal BCT pair; Main has magic, Sub does not > Sub has a newer Nintendo BCT
bool normal_main_magic = bct_block_has_modchip_magic(0x000); bool normal_main_magic = bct_block_has_modchip_magic(0x000);
bool normal_sub_magic = bct_block_has_modchip_magic(0x040); bool normal_sub_magic = bct_block_has_modchip_magic(0x040);
bool resynced = false;
if (normal_main_magic && !normal_sub_magic) { if (normal_main_magic && !normal_sub_magic) {
// BctNormalSub was updated by a firmware update but BctNormalMain write was // BctNormalSub was updated by a firmware update but BctNormalMain write was
// dropped by Atmosphere. copy Sub > Main to resync. // dropped by Atmosphere. copy Sub > Main to resync.
copy_bct(0x040, 0x000); copy_bct(0x040, 0x000);
resynced = true;
} }
// check Safe BCT pair; uses same logic // check Safe BCT pair; uses same logic
@ -797,10 +768,7 @@ bool check_and_resync_bct() {
if (safe_main_magic && !safe_sub_magic) { if (safe_main_magic && !safe_sub_magic) {
copy_bct(0x060, 0x020); copy_bct(0x060, 0x020);
resynced = true;
} }
return resynced;
} }
void write_payload() { void write_payload() {

View file

@ -19,7 +19,7 @@ fi
# detect distribution # detect distribution
if [ -f /etc/os-release ]; then if [ -f /etc/os-release ]; then
. /etc/os-release . /etc/os-release
DISTRO=${ID-LIKE:-$ID} DISTRO=$ID
else else
echo -e "${RED}Error: Cannot detect distribution${NC}" echo -e "${RED}Error: Cannot detect distribution${NC}"
exit 1 exit 1

View file

@ -12,7 +12,7 @@ echo -e "${GREEN}=== Picofly build script (multi-distro) ===${NC}\n"
# detect distribution # detect distribution
if [ -f /etc/os-release ]; then if [ -f /etc/os-release ]; then
. /etc/os-release . /etc/os-release
DISTRO=${ID_LIKE:-$ID} DISTRO=$ID
else else
echo -e "${RED}Error: Cannot detect distribution${NC}" echo -e "${RED}Error: Cannot detect distribution${NC}"
exit 1 exit 1

View file

@ -1 +0,0 @@
asdöfgljkklgj