text:
.program sd_clk
.side_set 1
.wrap_target
    ; open-drain RST switcher to keep the CPU in reset state
    set pindirs, 0     side 1 ; side-set push-pull eMMC clocker (2mA limit is set to prevent damage)
    irq clear 0        side 0
    set pindirs, 1     side 1
    irq clear 0        side 0
.wrap

.program out_cmd_or_dat
.wrap_target
    out x, 16
    irq wait 0 [1] ; the next cmd will go on falling edge
send_loop:
    out pindirs, 1 ; use open-drain just in case, to prevent 3.3v damage
    jmp x-- send_loop
    irq clear 1  ; unblock the reader
    out NULL, 32 ; clear the osr
.wrap

.program in_cmd_or_dat
.wrap_target
    out x, 32  ;get configuration
    irq wait 1 ;wait for cmd to send
    irq wait 0 ;sync with clock, next cmd will go at rising edge
data_wait:
    jmp pin, data_wait [1] ; sync pin wait with rising edge
read_loop:
    in pins, 1 ; here we always at the rising edge
    jmp x-- read_loop
    push
.wrap

.program glitch_sniff_cmd
.wrap_target
next_loop:
    mov x, osr ; mmc command pre-loaded bits count (48 - 1 - 1)
wait_for_start_bit:
    wait 0 pin, 31
    wait 1 pin, 31
    jmp pin wait_for_start_bit ; wait for cmd start bit on the rising edge
    wait 0 pin, 31
; waits separated by only 1 instruction, should be able to catch 50 MHz
    in NULL, 1
read_loop:
    wait 1 pin, 31
    in pins, 1 ; command sniffer
    wait 0 pin, 31
    jmp x-- read_loop
    irq clear 2 ; 'some cmd has passed' trigger
    mov x, isr ; save the last 16 bit of command
    push ; send the rest 16 bits of data
    jmp x != y, next_loop ; compare the glitch pattern (0x1351, read block + crc)
    irq clear 0 ; 'glitch pattern' trigger
.wrap

.program glitch_dat_waiter
.wrap_target
    mov x, y    ; data length pre-loaded counter (512 + 16 - 1) * 8
wait_for_zero_filtered:
    jmp pin, wait_for_zero_filtered
    jmp pin, wait_for_zero_filtered
    jmp pin, wait_for_zero_filtered
wait_for_data_pack:
    jmp x-- wait_for_data_pack
    irq clear 1 ; 'data transfer done' trigger
.wrap

.program glitch_trigger
.side_set 1
.wrap_target
    out x, 32 side 0   ; receive wait timing
    out y, 32 side 0   ; receive pulse timing
    irq wait 0 side 0  ; wait for read 13
    irq wait 1 side 0  ; wait for data transfer
    irq wait 2 side 0  ; wait for status request (should be NOPped for Mariko)
    irq wait 2 side 0  ; wait for status reply (should be NOPped for Mariko)
wait_for_timing:
    jmp x--, wait_for_timing side 0
glitch_en:
    jmp y--, glitch_en side 1
.wrap

repo_name: rehius/usk

repo_language: C

mime_type: text/plain


text:
;
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
;
; SPDX-License-Identifier: BSD-3-Clause
;

.program ws2812
.side_set 1

.define public T1 2
.define public T2 5
.define public T3 3

.lang_opt python sideset_init = pico.PIO.OUT_HIGH
.lang_opt python out_init     = pico.PIO.OUT_HIGH
.lang_opt python out_shiftdir = 1

.wrap_target
bitloop:
    out x, 1       side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
    jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
do_one:
    jmp  bitloop   side 1 [T2 - 1] ; Continue driving high, for a long pulse
do_zero:
    nop            side 0 [T2 - 1] ; Or drive low, for a short pulse
.wrap

% c-sdk {
#include "hardware/clocks.h"

static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) {

    pio_gpio_init(pio, pin);
    pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);

    pio_sm_config c = ws2812_program_get_default_config(offset);
    sm_config_set_sideset_pins(&c, pin);
    sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24);
    sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);

    int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
    float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
    sm_config_set_clkdiv(&c, div);

    pio_sm_init(pio, sm, offset, &c);
    pio_sm_set_enabled(pio, sm, true);
}
%}


text:
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "hardware/gpio.h"
#include "hardware/adc.h"
#include "pins.h"
#include "ws2812.pio.h"
#include "misc.h"
#include "board_detect.h"

extern int ws_pio_offset;

enum board_type {
    BOARD_WS = 0,
    BOARD_XO,
    BOARD_IB,
    BOARD_PI,
    BOARD_SQ
};

enum board_type cur_board = BOARD_WS;

bool detect_by_pull_up(int frc_pin, int det_pin)
{
    bool result = false;
    if (frc_pin >= 0)
        gpio_init(frc_pin);
    gpio_init(det_pin);
    if (frc_pin >= 0)
        gpio_set_dir(frc_pin, true);
    gpio_pull_up(det_pin);
    sleep_us(15);
    result = !gpio_get(det_pin);
    gpio_deinit(det_pin);
    if (frc_pin >= 0)
        gpio_deinit(frc_pin);
    gpio_disable_pulls(det_pin);
    return result;
}

bool test_xiao()
{
    return detect_by_pull_up(1, 2);
}

bool test_itsy()
{
    return detect_by_pull_up(3, 2);
}

bool test_pico()
{
    return detect_by_pull_up(-1, 22);
}

bool test_ws()
{
    return detect_by_pull_up(-1, 25);
}

bool test_sqc()
{
    return detect_by_pull_up(-1, 17);
}

void detect_board()
{
    gpio_pull_down(PIN_GLI_WS);
    gpio_pull_down(PIN_GLI_PICO);
    gpio_pull_down(PIN_GLI_XIAO);
    gpio_pull_down(PIN_GLI_ITSY);
    gpio_disable_input_output(PIN_RST);
    if (test_ws()) {
        cur_board = BOARD_WS;
    } else if (test_xiao()) {
        cur_board = BOARD_XO;
    } else if (test_itsy()) {
        cur_board = BOARD_IB;
    } else if (test_pico()) {
        cur_board = BOARD_PI;
    } else if (test_sqc()) {
        cur_board = BOARD_SQ;
    } else {
        cur_board = BOARD_WS;
    }
}

int led_pin()
{
    switch(cur_board){
        case BOARD_XO:
            return PIN_LED_XIAO;
        case BOARD_PI:
            return PIN_LED_PICO;
        case BOARD_IB:
            return PIN_LED_ITSY;
        default:
            return PIN_LED_WS;
    };
}

int pwr_pin()
{
    switch(cur_board){
        case BOARD_XO:
            return PIN_LED_PWR_XIAO;
        case BOARD_IB:
            return PIN_LED_PWR_ITSY;
        default:
            return 31;
    };
}

int scl_pin()
{
    switch(cur_board){
        case BOARD_XO:
            return PIN_SCL_XIAO;
        case BOARD_IB:
            return PIN_SCL_ITSY;
        case BOARD_PI:
            return PIN_SCL_PICO;
        case BOARD_SQ:
            return PIN_SCL_SQC;
        default:
            return PIN_SCL_WS;
    };
}

int sda_pin()
{
    switch(cur_board){
        case BOARD_XO:
            return PIN_SDA_XIAO;
        case BOARD_IB:
            return PIN_SDA_ITSY;
        case BOARD_PI:
            return PIN_SDA_PICO;
        case BOARD_SQ:
            return PIN_SDA_SQC;
        default:
            return PIN_SDA_WS;
    };
}

int gli_pin()
{
    switch(cur_board){
        case BOARD_XO:
            return PIN_GLI_XIAO;
        case BOARD_IB:
            return PIN_GLI_ITSY;
        case BOARD_PI:
            return PIN_GLI_PICO;
        default:
            return PIN_GLI_WS;
    };
}

bool is_pico()
{
    return cur_board == BOARD_PI;
}


text:
#include "stdint.h"

extern uint32_t ws_pio_offset;
extern uint32_t clk_pio_offset;
extern uint32_t sdin_pio_offset;
extern uint32_t sdout_pio_offset;
extern uint32_t gsniff_pio_offset;
extern uint32_t dsniff_pio_offset;
extern uint32_t gtrig_pio_offset;

void upload_pio();


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

#ifndef LINUX_MMC_MMC_H
#define LINUX_MMC_MMC_H

/* Standard MMC commands (4.1)           type  argument     response */
/* class 1 */
#define MMC_GO_IDLE_STATE         0   /* bc                          */
#define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
#define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
#define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
#define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
#define MMC_SLEEP_AWAKE           5   /* ac   [31:16] RCA 15:flg R1b */
#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
#define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
#define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
#define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
#define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
#define MMC_SEND_STATUS          13   /* ac   [31:16] RCA        R1  */
#define MMC_BUS_TEST_R           14   /* adtc                    R1  */
#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
#define MMC_BUS_TEST_W           19   /* adtc                    R1  */
#define MMC_SPI_READ_OCR         58   /* spi                  spi_R3 */
#define MMC_SPI_CRC_ON_OFF       59   /* spi  [0:0] flag      spi_R1 */

/* class 2 */
#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
#define MMC_SEND_TUNING_BLOCK    19   /* adtc                    R1  */
#define MMC_SEND_TUNING_BLOCK_HS200 21	/* adtc R1  */

/* class 3 */
#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */

/* class 4 */
#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */

/* class 6 */
#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */

/* class 5 */
#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
#define MMC_ERASE                38   /* ac                      R1b */

/* class 9 */
#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */

/* class 7 */
#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */

/* class 8 */
#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */

/* class 11 */
#define MMC_QUE_TASK_PARAMS      44   /* ac   [20:16] task id    R1  */
#define MMC_QUE_TASK_ADDR        45   /* ac   [31:0] data addr   R1  */
#define MMC_EXECUTE_READ_TASK    46   /* adtc [20:16] task id    R1  */
#define MMC_EXECUTE_WRITE_TASK   47   /* adtc [20:16] task id    R1  */
#define MMC_CMDQ_TASK_MGMT       48   /* ac   [20:16] task id    R1b */

/*
* MMC_SWITCH argument format:
*
*	[31:26] Always 0
*	[25:24] Access Mode
*	[23:16] Location of target Byte in EXT_CSD
*	[15:08] Value Byte
*	[07:03] Always 0
*	[02:00] Command Set
*/

/*
MMC status in R1, for native mode (SPI bits are different)
Type
e : error bit
s : status bit
r : detected and set for the actual command response
x : detected and set during command execution. the host must poll
the card by sending status command in order to read these bits.
Clear condition
a : according to the card state
b : always related to the previous command. Reception of
a valid command will clear it (with a delay of one command)
c : clear by read
*/

#define R1_OUT_OF_RANGE		(1 << 31)	/* er, c */
#define R1_ADDRESS_ERROR	(1 << 30)	/* erx, c */
#define R1_BLOCK_LEN_ERROR	(1 << 29)	/* er, c */
#define R1_ERASE_SEQ_ERROR      (1 << 28)	/* er, c */
#define R1_ERASE_PARAM		(1 << 27)	/* ex, c */
#define R1_WP_VIOLATION		(1 << 26)	/* erx, c */
#define R1_CARD_IS_LOCKED	(1 << 25)	/* sx, a */
#define R1_LOCK_UNLOCK_FAILED	(1 << 24)	/* erx, c */
#define R1_COM_CRC_ERROR	(1 << 23)	/* er, b */
#define R1_ILLEGAL_COMMAND	(1 << 22)	/* er, b */
#define R1_CARD_ECC_FAILED	(1 << 21)	/* ex, c */
#define R1_CC_ERROR		(1 << 20)	/* erx, c */
#define R1_ERROR		(1 << 19)	/* erx, c */
#define R1_UNDERRUN		(1 << 18)	/* ex, c */
#define R1_OVERRUN		(1 << 17)	/* ex, c */
#define R1_CID_CSD_OVERWRITE	(1 << 16)	/* erx, c, CID/CSD overwrite */
#define R1_WP_ERASE_SKIP	(1 << 15)	/* sx, c */
#define R1_CARD_ECC_DISABLED	(1 << 14)	/* sx, a */
#define R1_ERASE_RESET		(1 << 13)	/* sr, c */
#define R1_STATUS(x)            (x & 0xFFFFE000)
#define R1_CURRENT_STATE(x)	((x & 0x00001E00) >> 9)	/* sx, b (4 bits) */
#define R1_READY_FOR_DATA	(1 << 8)	/* sx, a */
#define R1_SWITCH_ERROR		(1 << 7)	/* sx, c */
#define R1_EXCEPTION_EVENT	(1 << 6)	/* sr, a */
#define R1_APP_CMD		(1 << 5)	/* sr, c */

#define R1_STATE_IDLE	0
#define R1_STATE_READY	1
#define R1_STATE_IDENT	2
#define R1_STATE_STBY	3
#define R1_STATE_TRAN	4
#define R1_STATE_DATA	5
#define R1_STATE_RCV	6
#define R1_STATE_PRG	7
#define R1_STATE_DIS	8

/*
* MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
* R1 is the low order byte; R2 is the next highest byte, when present.
*/
#define R1_SPI_IDLE		(1 << 0)
#define R1_SPI_ERASE_RESET	(1 << 1)
#define R1_SPI_ILLEGAL_COMMAND	(1 << 2)
#define R1_SPI_COM_CRC		(1 << 3)
#define R1_SPI_ERASE_SEQ	(1 << 4)
#define R1_SPI_ADDRESS		(1 << 5)
#define R1_SPI_PARAMETER	(1 << 6)
/* R1 bit 7 is always zero */
#define R2_SPI_CARD_LOCKED	(1 << 8)
#define R2_SPI_WP_ERASE_SKIP	(1 << 9)	/* or lock/unlock fail */
#define R2_SPI_LOCK_UNLOCK_FAIL	R2_SPI_WP_ERASE_SKIP
#define R2_SPI_ERROR		(1 << 10)
#define R2_SPI_CC_ERROR		(1 << 11)
#define R2_SPI_CARD_ECC_ERROR	(1 << 12)
#define R2_SPI_WP_VIOLATION	(1 << 13)
#define R2_SPI_ERASE_PARAM	(1 << 14)
#define R2_SPI_OUT_OF_RANGE	(1 << 15)	/* or CSD overwrite */
#define R2_SPI_CSD_OVERWRITE	R2_SPI_OUT_OF_RANGE

/*
* OCR bits are mostly in host.h
*/
#define MMC_CARD_BUSY	0x80000000	/* Card Power up status bit */

/*
* Card Command Classes (CCC)
*/
#define CCC_BASIC		(1<<0)	/* (0) Basic protocol functions */
/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
/* (and for SPI, CMD58,59) */
#define CCC_STREAM_READ		(1<<1)	/* (1) Stream read commands */
/* (CMD11) */
#define CCC_BLOCK_READ		(1<<2)	/* (2) Block read commands */
/* (CMD16,17,18) */
#define CCC_STREAM_WRITE	(1<<3)	/* (3) Stream write commands */
/* (CMD20) */
#define CCC_BLOCK_WRITE		(1<<4)	/* (4) Block write commands */
/* (CMD16,24,25,26,27) */
#define CCC_ERASE		(1<<5)	/* (5) Ability to erase blocks */
/* (CMD32,33,34,35,36,37,38,39) */
#define CCC_WRITE_PROT		(1<<6)	/* (6) Able to write protect blocks */
/* (CMD28,29,30) */
#define CCC_LOCK_CARD		(1<<7)	/* (7) Able to lock down card */
/* (CMD16,CMD42) */
#define CCC_APP_SPEC		(1<<8)	/* (8) Application specific */
/* (CMD55,56,57,ACMD*) */
#define CCC_IO_MODE		(1<<9)	/* (9) I/O mode */
/* (CMD5,39,40,52,53) */
#define CCC_SWITCH		(1<<10)	/* (10) High speed switch */
/* (CMD6,34,35,36,37,50) */
/* (11) Reserved */
/* (CMD?) */

/*
* CSD field definitions
*/

#define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
#define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */

#define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
#define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
#define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 - 3.2 - 3.31 */
#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */

/*
* EXT_CSD fields
*/

#define EXT_CSD_CMDQ_MODE_EN		15	/* R/W */
#define EXT_CSD_FLUSH_CACHE		32      /* W */
#define EXT_CSD_CACHE_CTRL		33      /* R/W */
#define EXT_CSD_POWER_OFF_NOTIFICATION	34	/* R/W */
#define EXT_CSD_PACKED_FAILURE_INDEX	35	/* RO */
#define EXT_CSD_PACKED_CMD_STATUS	36	/* RO */
#define EXT_CSD_EXP_EVENTS_STATUS	54	/* RO, 2 bytes */
#define EXT_CSD_EXP_EVENTS_CTRL		56	/* R/W, 2 bytes */
#define EXT_CSD_DATA_SECTOR_SIZE	61	/* R */
#define EXT_CSD_GP_SIZE_MULT		143	/* R/W */
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155	/* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE	156	/* R/W */
#define EXT_CSD_PARTITION_SUPPORT	160	/* RO */
#define EXT_CSD_HPI_MGMT		161	/* R/W */
#define EXT_CSD_RST_N_FUNCTION		162	/* R/W */
#define EXT_CSD_BKOPS_EN		163	/* R/W */
#define EXT_CSD_BKOPS_START		164	/* W */
#define EXT_CSD_SANITIZE_START		165     /* W */
#define EXT_CSD_WR_REL_PARAM		166	/* RO */
#define EXT_CSD_RPMB_MULT		168	/* RO */
#define EXT_CSD_FW_CONFIG		169	/* R/W */
#define EXT_CSD_BOOT_WP			173	/* R/W */
#define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */
#define EXT_CSD_PART_CONFIG		179	/* R/W */
#define EXT_CSD_ERASED_MEM_CONT		181	/* RO */
#define EXT_CSD_BUS_WIDTH		183	/* R/W */
#define EXT_CSD_STROBE_SUPPORT		184	/* RO */
#define EXT_CSD_HS_TIMING		185	/* R/W */
#define EXT_CSD_POWER_CLASS		187	/* R/W */
#define EXT_CSD_REV			192	/* RO */
#define EXT_CSD_STRUCTURE		194	/* RO */
#define EXT_CSD_CARD_TYPE		196	/* RO */
#define EXT_CSD_DRIVER_STRENGTH		197	/* RO */
#define EXT_CSD_OUT_OF_INTERRUPT_TIME	198	/* RO */
#define EXT_CSD_PART_SWITCH_TIME        199     /* RO */
#define EXT_CSD_PWR_CL_52_195		200	/* RO */
#define EXT_CSD_PWR_CL_26_195		201	/* RO */
#define EXT_CSD_PWR_CL_52_360		202	/* RO */
#define EXT_CSD_PWR_CL_26_360		203	/* RO */
#define EXT_CSD_SEC_CNT			212	/* RO, 4 bytes */
#define EXT_CSD_S_A_TIMEOUT		217	/* RO */
#define EXT_CSD_REL_WR_SEC_C		222	/* RO */
#define EXT_CSD_HC_WP_GRP_SIZE		221	/* RO */
#define EXT_CSD_ERASE_TIMEOUT_MULT	223	/* RO */
#define EXT_CSD_HC_ERASE_GRP_SIZE	224	/* RO */
#define EXT_CSD_BOOT_MULT		226	/* RO */
#define EXT_CSD_SEC_TRIM_MULT		229	/* RO */
#define EXT_CSD_SEC_ERASE_MULT		230	/* RO */
#define EXT_CSD_SEC_FEATURE_SUPPORT	231	/* RO */
#define EXT_CSD_TRIM_MULT		232	/* RO */
#define EXT_CSD_PWR_CL_200_195		236	/* RO */
#define EXT_CSD_PWR_CL_200_360		237	/* RO */
#define EXT_CSD_PWR_CL_DDR_52_195	238	/* RO */
#define EXT_CSD_PWR_CL_DDR_52_360	239	/* RO */
#define EXT_CSD_BKOPS_STATUS		246	/* RO */
#define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
#define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
#define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
#define EXT_CSD_PWR_CL_DDR_200_360	253	/* RO */
#define EXT_CSD_FIRMWARE_VERSION	254	/* RO, 8 bytes */
#define EXT_CSD_DEVICE_VERSION		262	/* RO, 2 bytes */
#define EXT_CSD_PRE_EOL_INFO		267	/* RO */
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A	268	/* RO */
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B	269	/* RO */
#define EXT_CSD_CMDQ_DEPTH		307	/* RO */
#define EXT_CSD_CMDQ_SUPPORT		308	/* RO */
#define EXT_CSD_SUPPORTED_MODE		493	/* RO */
#define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
#define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
#define EXT_CSD_MAX_PACKED_WRITES	500	/* RO */
#define EXT_CSD_MAX_PACKED_READS	501	/* RO */
#define EXT_CSD_BKOPS_SUPPORT		502	/* RO */
#define EXT_CSD_HPI_FEATURES		503	/* RO */

/*
* EXT_CSD field definitions
*/

#define EXT_CSD_WR_REL_PARAM_EN		(1<<2)

#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS	(0x40)
#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS	(0x10)
#define EXT_CSD_BOOT_WP_B_PERM_WP_EN	(0x04)
#define EXT_CSD_BOOT_WP_B_PWR_WP_EN	(0x01)

#define EXT_CSD_PART_CONFIG_ACC_MASK	(0x7)
#define EXT_CSD_PART_CONFIG_ACC_BOOT0	(0x1)
#define EXT_CSD_PART_CONFIG_ACC_RPMB	(0x3)
#define EXT_CSD_PART_CONFIG_ACC_GP0	(0x4)

#define EXT_CSD_PART_SETTING_COMPLETED	(0x1)
#define EXT_CSD_PART_SUPPORT_PART_EN	(0x1)

#define EXT_CSD_CMD_SET_NORMAL		(1<<0)
#define EXT_CSD_CMD_SET_SECURE		(1<<1)
#define EXT_CSD_CMD_SET_CPSECURE	(1<<2)

#define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
#define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
#define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
				 EXT_CSD_CARD_TYPE_HS_52)
#define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
/* DDR mode @1.8V or 3V I/O */
#define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
/* DDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
					| EXT_CSD_CARD_TYPE_DDR_1_2V)
#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run at 200MHz */
#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run at 200MHz */
/* SDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
					 EXT_CSD_CARD_TYPE_HS200_1_2V)
#define EXT_CSD_CARD_TYPE_HS400_1_8V	(1<<6)	/* Card can run at 200MHz DDR, 1.8V */
#define EXT_CSD_CARD_TYPE_HS400_1_2V	(1<<7)	/* Card can run at 200MHz DDR, 1.2V */
#define EXT_CSD_CARD_TYPE_HS400		(EXT_CSD_CARD_TYPE_HS400_1_8V | \
					 EXT_CSD_CARD_TYPE_HS400_1_2V)
#define EXT_CSD_CARD_TYPE_HS400ES	(1<<8)	/* Card can run at HS400ES */

#define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 bit mode */
#define EXT_CSD_DDR_BUS_WIDTH_4	5	/* Card is in 4 bit DDR mode */
#define EXT_CSD_DDR_BUS_WIDTH_8	6	/* Card is in 8 bit DDR mode */
#define EXT_CSD_BUS_WIDTH_STROBE (1<<7)	/* Enhanced strobe mode */

#define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
#define EXT_CSD_TIMING_HS	1	/* High speed */
#define EXT_CSD_TIMING_HS200	2	/* HS200 */
#define EXT_CSD_TIMING_HS400	3	/* HS400 */
#define EXT_CSD_DRV_STR_SHIFT	4	/* Driver Strength shift */

#define EXT_CSD_SEC_ER_EN	(1<<0)
#define EXT_CSD_SEC_BD_BLK_EN	(1<<2)
#define EXT_CSD_SEC_GB_CL_EN	(1<<4)
#define EXT_CSD_SEC_SANITIZE	(1<<6)  /* v4.5 only */

#define EXT_CSD_RST_N_EN_MASK	0x3
#define EXT_CSD_RST_N_ENABLED	1	/* RST_n is enabled on card */

#define EXT_CSD_NO_POWER_NOTIFICATION	0
#define EXT_CSD_POWER_ON		1
#define EXT_CSD_POWER_OFF_SHORT		2
#define EXT_CSD_POWER_OFF_LONG		3

#define EXT_CSD_PWR_CL_8BIT_MASK	0xF0	/* 8 bit PWR CLS */
#define EXT_CSD_PWR_CL_4BIT_MASK	0x0F	/* 8 bit PWR CLS */
#define EXT_CSD_PWR_CL_8BIT_SHIFT	4
#define EXT_CSD_PWR_CL_4BIT_SHIFT	0

#define EXT_CSD_PACKED_EVENT_EN	(1<<3)

/*
* EXCEPTION_EVENT_STATUS field
*/
#define EXT_CSD_URGENT_BKOPS		(1<<0)
#define EXT_CSD_DYNCAP_NEEDED		(1<<1)
#define EXT_CSD_SYSPOOL_EXHAUSTED	(1<<2)
#define EXT_CSD_PACKED_FAILURE		(1<<3)

#define EXT_CSD_PACKED_GENERIC_ERROR	(1<<0)
#define EXT_CSD_PACKED_INDEXED_ERROR	(1<<1)

/*
* BKOPS status level
*/
#define EXT_CSD_BKOPS_LEVEL_2		0x2

/*
* BKOPS modes
*/
#define EXT_CSD_MANUAL_BKOPS_MASK	0x01
#define EXT_CSD_AUTO_BKOPS_MASK		0x02

/*
* Command Queue
*/
#define EXT_CSD_CMDQ_MODE_ENABLED	(1<<0)
#define EXT_CSD_CMDQ_DEPTH_MASK		0x1F
#define EXT_CSD_CMDQ_SUPPORTED		(1<<0)

/*
* MMC_SWITCH access modes
*/
#define MMC_SWITCH_MODE_CMD_SET		0x00	/* Change the command set */
#define MMC_SWITCH_MODE_SET_BITS	0x01	/* Set bits which are 1 in value */
#define MMC_SWITCH_MODE_CLEAR_BITS	0x02	/* Clear bits which are 1 in value */
#define MMC_SWITCH_MODE_WRITE_BYTE	0x03	/* Set target to value */

/*
* Erase/trim/discard
*/
#define MMC_ERASE_ARG			0x00000000
#define MMC_SECURE_ERASE_ARG		0x80000000
#define MMC_TRIM_ARG			0x00000001
#define MMC_DISCARD_ARG			0x00000003
#define MMC_SECURE_TRIM1_ARG		0x80000001
#define MMC_SECURE_TRIM2_ARG		0x80008000
#define MMC_SECURE_ARGS			0x80000000
#define MMC_TRIM_ARGS			0x00008001

#endif /* LINUX_MMC_MMC_H */

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

#ifndef LINUX_MMC_SD_H
#define LINUX_MMC_SD_H

/* SD commands                           type  argument     response */
  /* class 0 */
/* This is basically the same command as for MMC with some quirks. */
#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
#define SD_SWITCH_VOLTAGE         11  /* ac                      R1  */

  /* class 10 */
#define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */

  /* class 5 */
#define SD_ERASE_WR_BLK_START    32   /* ac   [31:0] data addr   R1  */
#define SD_ERASE_WR_BLK_END      33   /* ac   [31:0] data addr   R1  */

  /* Application commands */
#define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
#define SD_APP_SD_STATUS         13   /* adtc                    R1  */
#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
#define SD_APP_SEND_SCR          51   /* adtc                    R1  */

/* OCR bit definitions */
#define SD_OCR_S18R		(1 << 24)    /* 1.8V switching request */
#define SD_ROCR_S18A		SD_OCR_S18R  /* 1.8V switching accepted by card */
#define SD_OCR_XPC		(1 << 28)    /* SDXC power control */
#define SD_OCR_CCS		(1 << 30)    /* Card Capacity Status */
#define SD_OCR_VDD_27_34    (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
#define SD_OCR_VDD_32_33    (1 << 20)	 /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_VDD_18       (1 << 7)	 /* VDD voltage 1.8 */

/*
 * SD_SWITCH argument format:
 *
 *      [31] Check (0) or switch (1)
 *      [30:24] Reserved (0)
 *      [23:20] Function group 6
 *      [19:16] Function group 5
 *      [15:12] Function group 4
 *      [11:8] Function group 3
 *      [7:4] Function group 2
 *      [3:0] Function group 1
 */

/*
 * SD_SEND_IF_COND argument format:
 *
 *	[31:12] Reserved (0)
 *	[11:8] Host Voltage Supply Flags
 *	[7:0] Check Pattern (0xAA)
 */

/*
 * SCR field definitions
 */

#define SCR_SPEC_VER_0		0	/* Implements system specification 1.0 - 1.01 */
#define SCR_SPEC_VER_1		1	/* Implements system specification 1.10 */
#define SCR_SPEC_VER_2		2	/* Implements system specification 2.00-3.0X */

/*
 * SD bus widths
 */
#define SD_BUS_WIDTH_1		0
#define SD_BUS_WIDTH_4		2

/*
 * SD_SWITCH mode
 */
#define SD_SWITCH_CHECK		0
#define SD_SWITCH_SET		1

/*
 * SD_SWITCH function groups
 */
#define SD_SWITCH_GRP_ACCESS	0

/*
 * SD_SWITCH access modes
 */
#define SD_SWITCH_ACCESS_DEF	0
#define SD_SWITCH_ACCESS_HS	1

#endif /* LINUX_MMC_SD_H */


text:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "pico/stdlib.h"
#include "hardware/adc.h"
#include "hardware/pio.h"
#include "hardware/clocks.h"
#include "hardware/vreg.h"
#include "hardware/xosc.h"
#include "hardware/watchdog.h"
#include "boot_detect.h"
#include "board_detect.h"
#include "config.h"

#include "misc.h"
#include "glitch.h"
#include "fuses.h"
#include "pio_upload.h"
#include "pins.h"

bool write_payload();

// overclock to 300 MHz
void init_system() {
    vreg_set_voltage(VREG_VOLTAGE_1_30);
	set_sys_clock_khz(300000, true);
}

// filled within "fast check" on eMMC init
extern uint8_t cid_buf[17];

void rewrite_payload()
{
    put_pixel(PIX_whi);
    write_payload();
    put_pixel(PIX_blu);
    // used to automatically rewrite payload when eMMC/console changes
    init_config(cid_buf + 1);
}

bool safe_test_voltage(int pin, float target, float range)
{
    gpio_enable_input_output(pin);
    adc_gpio_init(pin);
    adc_select_input(pin - 26);
    uint16_t result = adc_read();
    gpio_disable_input_output(pin);
    float voltage = result * 3.3f / (1 << 12);
    return voltage >= (target - range) && voltage <= (target + range);
}

// test all ADC pins
void self_test()
{
    absolute_time_t tio_time = make_timeout_time_ms(2500);
    adc_init();
    bool rst_ok = false, cmd_ok = false, d0_ok = false, clk_ok = false;
    while (!time_reached(tio_time)) {
        if (!rst_ok)
            rst_ok |= safe_test_voltage(PIN_RST, 1.8f, 0.2f);
        if (!cmd_ok)
            cmd_ok |= safe_test_voltage(PIN_CMD, 1.8f, 0.2f);
        if (!d0_ok)
            d0_ok |= safe_test_voltage(PIN_DAT, 1.8f, 0.2f);
        if (rst_ok && cmd_ok && d0_ok)
            break;
    }
    if(!rst_ok)
    {
        halt_with_error(0, 2);
    }
    if(!cmd_ok)
    {
        halt_with_error(1, 2);
    }
    if(!d0_ok)
    {
        halt_with_error(2, 2);
    }
}

extern bool was_self_reset;

int main()
{
    // stop watchdog
    *(uint32_t*)(0x40058000 + 0x3000) = (1 << 30);
    // init reset, mosfet and LED
    detect_board();
    // clocks & voltage
	init_system();
    // fuses counter
    init_fuses();
    // LED & glitch & emmc PIO
    upload_pio();
    // check if this is the very first start
    if (watchdog_caused_reboot() && boot_try == 0)
	{
		halt_with_error(1, 1);
	}
    // is chip reset required
    bool force_button = detect_by_pull_up(1, 0);
    // start LED
    put_pixel(PIX_blu);
    // test pins
    self_test();
    // wait till the CPU has proper power & started reading the eMMC
    wait_for_boot(2500);
    // ensure the BCT has not been overwritten by system update
    bool force_check = fast_check();
    was_self_reset = force_button || !is_configured(cid_buf + 1);
    // perform payload rewrite if required
    if (!force_check || was_self_reset) {
        rewrite_payload();
    }
    // setup the glitch trigger for Mariko
    if (mariko) {
        pio1->instr_mem[gtrig_pio_offset + 4] = pio_encode_nop();
        pio1->instr_mem[gtrig_pio_offset + 5] = pio_encode_nop();
    }
    // start from some default width
    int width = 150;
    bool glitched = false;
    int offset = 0;
    for (int full_try = 0; full_try < 2; full_try++) {
        // try saved records
        for (int y = 0; (y < 2) && !glitched; y++) {
            int max_weight = -1;
            while (1) {
                offset = find_best_record(&max_weight);
                if (offset == -1)
                    break;
                // try glitch
                glitched = glitch_try_offset(offset, &width, 3);
                if (glitched)
                    break;
            }
        }
        if (!glitched) {
            for(int z = 0; (z < 2) && !glitched; z++) {
                prepare_random_array();
                for(int y = 0; y < OFFSET_CNT; y++)
                {
                    offset = offsets_array[y];
                    glitched = glitch_try_offset(offset, &width, 4);
                    if (glitched)
                        break;
                }
            }
        }
        if (glitched) {
            if ((count_fuses() & 1) != boot_slot)
            {
                // finish update / rollback
                burn_fuse();
            }
            add_boot_record(offset);
            halt_with_error(0, 1);
        }
        if (full_try == 0) {
            rewrite_payload();
        }
    }
    // attempts limit
    halt_with_error(7, 3);
}


text:
#include "stdbool.h"

bool detect_by_pull_up(int frc_pin, int det_pin);

void detect_board();
int gli_pin();
int pwr_pin();
int led_pin();
bool is_pico();
int scl_pin();
int sda_pin();


text:
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "pins.h"
#include <string.h>
#include "hardware/vreg.h"
#include "ws2812.pio.h"
#include "board_detect.h"
#include "misc.h"
#include "board_detect.h"

extern int ws_pio_offset;

#define BLINK_TIME 700
#define SHORT_TIME ( BLINK_TIME * 2 / 10 )
#define SHORT_PAUSE_TIME ((BLINK_TIME - SHORT_TIME) / 2)
#define LONG_TIME ( BLINK_TIME * 8 / 10 )
#define LONG_PAUSE_TIME ((BLINK_TIME - LONG_TIME) / 2)
#define PAUSE_BETWEEN 2000
#define PAUSE_BEFORE 750
#define CODE_REPEATS 3

#define GPIO_OD PADS_BANK0_GPIO0_OD_BITS
#define GPIO_IE PADS_BANK0_GPIO0_IE_BITS
#define GPIO_OD_PD (GPIO_OD | PADS_BANK0_GPIO0_PDE_BITS)

#define PTR_SAFE_RAM4 (void*)0x20040200

typedef void nopar();

void __not_in_flash_func(zzz)() {
    static bool not_first = 0;
    if(!not_first)
    {
        not_first = 1;
        memcpy(PTR_SAFE_RAM4, (void*)((uint32_t)zzz - 1), 0x200);
        ((nopar*)(PTR_SAFE_RAM4 + 1))();
    }
    *(uint32_t*)(0x4000803C + 0x3000) = 1;  // go to 12 MHz
    uint32_t * vreg = (uint32_t*)0x40064000;
    vreg[1] &= ~1;  // disable brownout
    *(uint32_t*)0x40060000 = 0x00d1e000; // disable rosc
    *(uint32_t*)0x40004018 = 0xFF ^ (1 << 4);  // disable SRAMs except ours
    vreg[0] = 1;    // lowest possible power
    *(uint32_t*)0x40024000 = 0x00d1e000; // disable xosc
    while(1);
}

void finish_pins_except_leds() {
    for(int pin = 0; pin <= 29; pin += 1) {
        if (pin == led_pin() || pin == pwr_pin())
            continue;
        if (pin == PIN_GLI_PICO || pin == PIN_GLI_XIAO || pin == PIN_GLI_WS || pin == PIN_GLI_ITSY)
        {
            gpio_pull_down(pin);
        }
        else
        {
            gpio_disable_pulls(pin);
        }
        gpio_disable_input_output(pin);
    }
}

void finish_pins_leds() {
    gpio_disable_input_output(led_pin());
    gpio_disable_input_output(pwr_pin());
}

void halt_with_error(uint32_t err, uint32_t bits)
{
    finish_pins_except_leds();
    pio_set_sm_mask_enabled(pio0, 0xF, false);
    pio_set_sm_mask_enabled(pio1, 0xF, false);
    set_sys_clock_khz(48000, true);
    vreg_set_voltage(VREG_VOLTAGE_0_95);
    if (bits != 1)
    {
        put_pixel(0);
        sleep_ms(PAUSE_BEFORE);
    }
    for(int j = 0; j < CODE_REPEATS; j++)
    {
        for(int i = 0; i < bits; i++)
        {
            bool is_long = err & (1 << (bits - i - 1));
            sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
            bool success = bits == 1 && is_long == 0;
            if (success)
                put_pixel(PIX_whi);
            else
                put_pixel(PIX_yel);
            sleep_ms(is_long ? LONG_TIME : success ? SHORT_TIME * 2 : SHORT_TIME);
            put_pixel(0);
            if (i != bits - 1 || j != CODE_REPEATS - 1)
                sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
            if (i == bits - 1 && j != CODE_REPEATS - 1)
                sleep_ms(PAUSE_BETWEEN);
        }
        // first write case, do not repeat this kind of error code
        if (bits == 1)
            break;
    }
    finish_pins_leds();
    zzz();
}

void put_pixel(uint32_t pixel_grb)
{
    static bool led_enabled = false;
    if (is_pico())
    {
        gpio_init(led_pin());
        if (pixel_grb) {
            gpio_set_dir(led_pin(), true);
            gpio_put(led_pin(), 1);
        }
        return;
    }
    ws2812_program_init(pio0, 3, ws_pio_offset, led_pin(), 800000, true);
    if (!led_enabled && pwr_pin() != 31)
    {
        led_enabled = true;
        gpio_init(pwr_pin());
        gpio_set_drive_strength(pwr_pin(), GPIO_DRIVE_STRENGTH_12MA);
        gpio_set_dir(pwr_pin(), true);
        gpio_put(pwr_pin(), 1);
        sleep_us(200);
    }
    pio_sm_put_blocking(pio0, 3, pixel_grb << 8u);
    sleep_us(50);
    pio_sm_set_enabled(pio0, 3, false);
    gpio_init(led_pin());
}

void gpio_disable_input_output(int pin)
{
    uint32_t pad_reg = 0x4001c000 + 4 + pin*4;
    *(uint32_t*)(pad_reg + 0x2000) = GPIO_OD;
    *(uint32_t*)(pad_reg + 0x3000) = GPIO_IE;
}

void gpio_enable_input_output(int pin)
{
    uint32_t pad_reg = 0x4001c000 + 4 + pin*4;
    *(uint32_t*)(pad_reg + 0x3000) = GPIO_OD;
    *(uint32_t*)(pad_reg + 0x2000) = GPIO_IE;
}

void reset_cpu() {
    gpio_enable_input_output(PIN_RST);
    gpio_pull_up(PIN_RST);
    sleep_us(1000);
    gpio_init(PIN_RST);
    gpio_set_dir(PIN_RST, true);
    sleep_us(2000);
    gpio_deinit(PIN_RST);
    gpio_disable_pulls(PIN_RST);
    gpio_disable_input_output(PIN_RST);
}


text:
#include "fuses.h"
#include "stdint.h"
#include "string.h"
#include "hardware/watchdog.h"

// firmware info from the bootloader & flash
int boot_slot = 0;
int boot_try = 0;

// firmware update fuse count calculator
int count_fuses()
{
    int weight = 0;
    uint32_t * buf = (uint32_t*)fuses;
    for (int i = 0; i < 64; i++) {
        if(buf[i] == 0)
            weight += 32;
        else {
            weight += __builtin_ctz(buf[i]);
            break;
        }
    }
    return weight;
}

// firmware update fuse burner
void burn_fuse()
{
    uint32_t buf[64];
    memcpy(buf, fuses, 256);
    for (int i = 0; i < 64; i++) {
        if (buf[i] != 0) {
            int tz = __builtin_ctz(buf[i]);
            buf[i] &= ~(1 << tz);
            flash_range_program(FUSE_OFF, (uint8_t*)buf, 256);
            return;
        }
    }
	flash_range_erase(FUSE_OFF, 0x1000);
	burn_fuse(); // burn one more because both 0 and 256*8 are even
}

void init_fuses()
{
    boot_slot = watchdog_hw->scratch[1];
    boot_try = watchdog_hw->scratch[0];
}


text:
#include "pico/stdlib.h"
#include "config.h"
#include "fuses.h"
#include <stdio.h>
#include <string.h>

typedef struct usk_cfg {
    uint8_t cid[16];
    uint8_t sign;
    uint8_t version_hi;
    uint8_t version_lo;
    uint8_t lock;
    uint16_t pcrc;
} usk_cfg;

#define VER_SIGN sizeof(usk_cfg)

uint16_t payload_crc();

#define typed_cfg ((const usk_cfg *)flash_cfg)

bool is_inited() {
    return typed_cfg->sign == VER_SIGN
    && typed_cfg->version_hi == VER_HI
    && typed_cfg->version_lo == VER_LO
    && payload_crc() == typed_cfg->pcrc;
}

bool is_configured(uint8_t * cid) {
    bool cid_ok = memcmp(typed_cfg->cid, cid, 16) == 0;
    bool init_ok = is_inited();
    return cid_ok && init_ok;
}

bool check_blank_config(int start, int size) {
    for(int i = start; i < start + size; i+= 4) {
        uint32_t val = *(volatile uint32_t*)(flash_cfg + i);
        if (val != 0xFFFFFFFF)
            return false;
    }
    return true;
}

void erase_config() {
    for (int i = 0; i < CONFIG_SIZE; i += 0x1000) {
        if (!check_blank_config(i, 0x1000)) {
            flash_range_erase(CONFIG_START + i, 0x1000);
        }
    }
}

bool is_locked() {
    return typed_cfg->lock != 0xFF;
}

void lock_config() {
    if (is_locked())
        return;
    uint8_t buf[256];
    usk_cfg * cfg = (usk_cfg *)buf;
    memcpy(buf, flash_cfg, 256);
    cfg->lock = 0;
    flash_range_program(CONFIG_START, buf, 256);
}

extern int boot_slot;

void init_config(uint8_t * cid) {
    erase_config();
    uint8_t buf[256];
    memset(buf, 0xFF, 256);
    usk_cfg * cfg = (usk_cfg *)buf;
    memcpy(cfg->cid, cid, 16);
    cfg->sign = VER_SIGN;
    cfg->version_hi = VER_HI;
    cfg->version_lo = VER_LO;
    cfg->pcrc = payload_crc();
    flash_range_program(CONFIG_START, buf, 256);
}
void add_boot_record(int offset) {
    if (is_locked()) {
        return;
    }
    uint32_t buf[64];
    memcpy(buf, flash_cfg + CONFIG_IDX(offset) * 256, 256);
    for (int i = 0; i < 64; i++) {
        if (buf[i] != 0) {
            int tz = __builtin_ctz(buf[i]);
            buf[i] &= ~(1 << tz);
            flash_range_program(CONFIG_START + CONFIG_IDX(offset) * 256, (uint8_t*)buf, 256);
            return;
        }
    }
    lock_config();
}

int get_weigth(int offset) {
    int weight = 0;
    uint32_t * buf = (uint32_t*) (flash_cfg + CONFIG_IDX(offset) * 256);
    for (int i = 0; i < 64; i++) {
        if(buf[i] == 0)
            weight += 32;
        else {
            weight += __builtin_ctz(buf[i]);
            break;
        }
    }
    return weight;
}

int find_best_record(int * max_weight) {
    static int last_weight = -1;
    static int last_offset = 0;
    int best_offset = -1;
    int best_weight = 0;
    for (int i = OFFSET_MIN; i < OFFSET_MAX; i += OFFSET_DIV) {
        int cur_weight = get_weigth(i);
        if (cur_weight > best_weight) {
            if (*max_weight == -1 || cur_weight < *max_weight
            || (cur_weight == *max_weight && *max_weight == last_weight &&
                last_offset < i)) {
                best_offset = i;
                best_weight = cur_weight;
            }
        }
    }
    if (best_offset != -1) {
        *max_weight = best_weight;
    }
    last_weight = best_weight;
    last_offset = best_offset;
    return best_offset;
}


text:
#include "config.h"
#define GLITCH_RESULT_SUCCESS 0 // glitch worked and loaded
#define GLITCH_RESULT_MISSING 1 // trigger is missing
#define GLITCH_RESULT_FAILURE 2 // glitch did not work
#define GLITCH_RESULT_TIMEOUT 3 // glitch worked, but timed out
#define G_SNIFF_SM 0
#define G_TRIG_SM  1
#define G_DAT0_SM  2
int do_glitch(int delay, int width, int total_ms, int after_ms);
void init_glitch_pio();
void deinit_glitch_pio();
bool glitch_try_offset(int offset, int * width, int edge_limit);
void prepare_random_array();
extern int offsets_array[OFFSET_CNT];


text:
#define PIX_blu 0x00003F
#define PIX_yel 0x151500
#define PIX_whi 0x111111

#define PIX_b 0x00000F

void put_pixel(uint32_t pixel_grb);

void halt_with_error(uint32_t err, uint32_t bits);

void gpio_disable_input_output(int pin);

void gpio_enable_input_output(int pin);

void finish_pins_except_leds();

void reset_cpu();


text:
#include "hardware/flash.h"

// firmware info from the bootloader & flash
extern int boot_slot;
extern int boot_try;

int count_fuses();
void init_fuses();
void burn_fuse();

#define FUSE_OFF 0xF000
#define fuses ((const uint8_t *) (XIP_BASE + FUSE_OFF))


text: # μsk


text:
name: Build PicoFly binaries

on:
  workflow_dispatch:

permissions:
  contents: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Install dependencies
        run: sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential

      - name: Checkout rehius/usk
        uses: actions/checkout@v3
        with:
          repository: rehius/usk
          path: usk

      - name: Checkout rehius/busk
        uses: actions/checkout@v3
        with:
          repository: rehius/busk
          path: busk

      - name: Checkout raspberrypi/pico-sdk
        uses: actions/checkout@v3
        with:
          repository: raspberrypi/pico-sdk
          path: pico-sdk
          submodules: recursive

      - name: Set PICO_SDK_PATH environment variable
        run: |
          echo "PICO_SDK_PATH=$GITHUB_WORKSPACE/pico-sdk" >> $GITHUB_ENV
      - name: Create symbolic link of pico_sdk_import.cmake in busk and usk sources
        run: |
          ln -s $PICO_SDK_PATH/external/pico_sdk_import.cmake $GITHUB_WORKSPACE/busk/pico_sdk_import.cmake
          ln -s $PICO_SDK_PATH/external/pico_sdk_import.cmake $GITHUB_WORKSPACE/usk/pico_sdk_import.cmake
      - name: Create 'generated' directory in usk source directory
        run: mkdir -p $GITHUB_WORKSPACE/usk/generated

      - name: Build busk
        run: |
          # Backup and modify memmap_default.ld for busk build
          cp $GITHUB_WORKSPACE/pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld $GITHUB_WORKSPACE/pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld.bak
          sed -i 's/RAM(rwx) : ORIGIN =  0x20000000, LENGTH = 256k/RAM(rwx) : ORIGIN = 0x20038000, LENGTH = 32k/g' $GITHUB_WORKSPACE/pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld
          mkdir -p $GITHUB_WORKSPACE/build/busk
          cd $GITHUB_WORKSPACE/build/busk
          cmake $GITHUB_WORKSPACE/busk
          make
          make clean
          cd $GITHUB_WORKSPACE
          # Restore original memmap_default.ld from backup
          rm -f $GITHUB_WORKSPACE/pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld
          mv $GITHUB_WORKSPACE/pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld.bak $GITHUB_WORKSPACE/pico-sdk/src/rp2_common/pico_standard_link/memmap_default.ld

      - name: Build usk
        run: |
          mkdir -p $GITHUB_WORKSPACE/build/usk
          cd $GITHUB_WORKSPACE/build/usk
          cmake $GITHUB_WORKSPACE/usk
          make
          make clean
          python3 $GITHUB_WORKSPACE/usk/prepare.py
          cd $GITHUB_WORKSPACE
      - name: Generate release tag
        id: tag
        run: |
          USK_VERSION_LO=$(sed -n 's/#define VER_LO \([0-9]*\)/\1/p' $GITHUB_WORKSPACE/usk/config.h)
          USK_VERSION_HI=$(sed -n 's/#define VER_HI \([0-9]*\)/\1/p' $GITHUB_WORKSPACE/usk/config.h)
          USK_VERSION=${USK_VERSION_HI}.${USK_VERSION_LO}
          RELEASE_TAG=PicoFly_${USK_VERSION}_$(date +"%Y.%m.%d_%H-%M")
          echo "release_tag=$RELEASE_TAG" >> $GITHUB_OUTPUT
          echo "release_tag=$RELEASE_TAG"

      - name: Createa a release
        uses: softprops/action-gh-release@v1
        with:
          tag_name: ${{ steps.tag.outputs.release_tag }}
          files: |
            build/usk/firmware.uf2
            build/usk/update.bin


text:
# Contribution Guidelines

Please ensure your pull request adheres to the following guidelines:

- Search previous suggestions before making a new one, as yours may be a duplicate.
- Make an individual pull request for each suggestion.
- Edit [applications.json](https://github.com/serhii-londar/open-source-mac-os-apps/blob/master/applications.json) instead of [README.md](https://github.com/serhii-londar/open-source-mac-os-apps/blob/master/README.md).
- Use the following format:
```json
    {
            "short_description": "Description of repository",
            "categories": [
                "Application category 1",
                "Application category 2"
            ],
            "repo_url": "Link to repository",
            "title": "Name of application",
            "icon_url": "URL to application icon",
            "screenshots": [
               "Screenshot url 1",
               "Screenshot url 2"
            ],
            "official_site": "Official site link",
            "languages": [
                "Language name"
            ]
        }
```
- New categories, or improvements to the existing categorization are welcome. List of all categories can be found in [categories.json](https://github.com/serhii-londar/open-source-mac-os-apps/blob/master/categories.json).
- Keep descriptions short and simple, but descriptive.
- End all descriptions with a full stop/period.
- Check your spelling and grammar.
- Make sure your text editor is set to remove trailing whitespace.

#### Deleting

Typical reasons for deleting a project:

- Doesn't build in the current Xcode
- No updates / no longer works
- Deprecated
- Lacks license

#### Projects are ineligible if:

- Lack recent commit
- README is not clear or not written in English

Your contributions are always welcome! Thank you for your suggestions! :smiley:

mime_type: text/xml