diff --git a/ipl/arm64.h b/ipl/arm64.h new file mode 100755 index 0000000..da15bf1 --- /dev/null +++ b/ipl/arm64.h @@ -0,0 +1,35 @@ +/* +* Copyright (c) 2018 naehrwert +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#ifndef _ARM64_H_ +#define _ARM64_H_ + +#include "types.h" + +#define LSL0 0 +#define LSL16 16 +#define LSL32 32 + +#define _PAGEOFF(x) ((x) & 0xFFFFF000) + +#define _ADRP(r, o) 0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F) +#define _BL(a, o) 0x94000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF) +#define _B(a, o) 0x94000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF) +#define _MOVKX(r, i, s) 0xF2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F) +#define _MOVZX(r, i, s) 0xD2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F) +#define _NOP() 0xD503201F + +#endif diff --git a/ipl/btn.c b/ipl/btn.c index eb12ffe..78c70eb 100755 --- a/ipl/btn.c +++ b/ipl/btn.c @@ -37,22 +37,21 @@ u32 btn_wait() u32 res = 0, btn = btn_read(); int pwr = 0; - // Power button down, raise a filter. + //Power button down, raise a filter. if (btn & BTN_POWER) { pwr = 1; - btn &= 0xFFFFFFFE; + btn &= ~BTN_POWER; } do { res = btn_read(); - // Power button up, remove filter. + //Power button up, remove filter. if (!(res & BTN_POWER) && pwr) pwr = 0; - // Power button still down. - else if (pwr) - res &= 0xFFFFFFFE; + else if (pwr) //Power button still down. + res &= ~BTN_POWER; } while (btn == res); return res; diff --git a/ipl/di.c b/ipl/di.c index 511bc55..c5383fa 100755 --- a/ipl/di.c +++ b/ipl/di.c @@ -22,6 +22,8 @@ #include "i2c.h" #include "pmc.h" #include "max77620.h" +#include "gpio.h" +#include "pinmux.h" #include "di.inl" @@ -56,25 +58,25 @@ void display_init() PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000; //Config pins. - PINMUX_AUX(0x1D0) &= 0xFFFFFFEF; - PINMUX_AUX(0x1D4) &= 0xFFFFFFEF; - PINMUX_AUX(0x1FC) &= 0xFFFFFFEF; - PINMUX_AUX(0x200) &= 0xFFFFFFEF; - PINMUX_AUX(0x204) &= 0xFFFFFFEF; + PINMUX_AUX(PINMUX_AUX_NFC_EN) &= 0xFFFFFFEF; + PINMUX_AUX(PINMUX_AUX_NFC_INT) &= 0xFFFFFFEF; + PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= 0xFFFFFFEF; + PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= 0xFFFFFFEF; + PINMUX_AUX(PINMUX_AUX_LCD_RST) &= 0xFFFFFFEF; - GPIO_3(0x00) = (GPIO_3(0x00) & 0xFFFFFFFC) | 0x3; - GPIO_3(0x10) = (GPIO_3(0x10) & 0xFFFFFFFC) | 0x3; - GPIO_3(0x20) = (GPIO_3(0x20) & 0xFFFFFFFE) | 0x1; - - sleep(10000u); - - GPIO_3(0x20) = (GPIO_3(0x20) & 0xFFFFFFFD) | 0x2; + gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO); //Backlight +-5V. + gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE); //Backlight +-5V. + gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); //Backlight +5V enable. sleep(10000); - GPIO_6(0x04) = (GPIO_6(0x04) & 0xFFFFFFF8) | 0x7; - GPIO_6(0x14) = (GPIO_6(0x14) & 0xFFFFFFF8) | 0x7; - GPIO_6(0x24) = (GPIO_6(0x24) & 0xFFFFFFFD) | 0x2; + gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); //Backlight -5V enable. + + sleep(10000); + + gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO); //Backlight PWM, Enable, Reset. + gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE); + gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); //Backlight Enable enable. //Config display interface and display. MIPI_CAL(0x60) = 0; @@ -85,7 +87,7 @@ void display_init() sleep(10000); - GPIO_6(0x24) = (GPIO_6(0x24) & 0xFFFFFFFB) | 0x4; + gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH); //Backlight Reset enable. sleep(60000); @@ -135,13 +137,16 @@ void display_init() void display_backlight(u8 enable) { - GPIO_6(0x24) = (GPIO_6(0x24) & 0xFFFFFFFE) | (enable & 1); + gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); //Backlight PWM. } void display_end() { display_backlight(0); - DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1; + + //TODO: figure out why this freezes. + + /*DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1; DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; u32 end = HOST1X(0x30A4) + 5; @@ -164,17 +169,17 @@ void display_end() sleep(50000); - GPIO_6(0x24) &= 0xFFFFFFFB; + //gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable. - sleep(10000); + //sleep(10000); - GPIO_3(0x20) &= 0xFFFFFFFD; + //gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable. - sleep(10000); + //sleep(10000); - GPIO_3(0x20) = (GPIO_3(0x20) >> 1) << 1; + //gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable. - sleep(10000); + //sleep(10000); //Disable clocks. CLOCK(0x308) = 0x1010000; @@ -183,12 +188,12 @@ void display_end() CLOCK(0x324) = 0x18000000; DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF); - DSI(_DSIREG(DSI_POWER_CONTROL)) = 0; + DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;*/ - GPIO_6(0x04) &= 0xFFFFFFFE; + gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); //Backlight PWM. - PINMUX_AUX(0x1FC) = (PINMUX_AUX(0x1FC) & 0xFFFFFFEF) | 0x10; - PINMUX_AUX(0x1FC) = (PINMUX_AUX(0x1FC) >> 2) << 2 | 1; + PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFEF) | 0x10; + PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; } void display_color_screen(u32 color) diff --git a/ipl/gfx.c b/ipl/gfx.c index 3c67be1..f718b5e 100755 --- a/ipl/gfx.c +++ b/ipl/gfx.c @@ -320,8 +320,8 @@ void gfx_set_pixel(gfx_ctxt_t *ctxt, u32 x, u32 y, u32 color) void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color) { - int dx = abs(x1-x0), sx = x0 < x1 ? 1 : -1; - int dy = abs(y1-y0), sy = y0 < y1 ? 1 : -1; + int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1; int err = (dx > dy ? dx : -dy) / 2, e2; while (1) @@ -330,7 +330,15 @@ void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color) if (x0 == x1 && y0 == y1) break; e2 = err; - if (e2 >-dx) { err -= dy; x0 += sx; } - if (e2 < dy) { err += dx; y0 += sy; } + if (e2 >-dx) + { + err -= dy; + x0 += sx; + } + if (e2 < dy) + { + err += dx; + y0 += sy; + } } } diff --git a/ipl/hos.c b/ipl/hos.c index a8df029..0cb8e09 100755 --- a/ipl/hos.c +++ b/ipl/hos.c @@ -31,6 +31,7 @@ #include "pkg1.h" #include "pkg2.h" #include "ff.h" +#include "di.h" #include "gfx.h" extern gfx_ctxt_t gfx_ctxt; @@ -73,9 +74,9 @@ typedef struct _merge_kip_t #define KB_FIRMWARE_VERSION_301 2 #define KB_FIRMWARE_VERSION_400 3 #define KB_FIRMWARE_VERSION_500 4 +#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_500 -#define NUM_KEYBLOB_KEYS 5 -static const u8 keyblob_keyseeds[NUM_KEYBLOB_KEYS][0x10] = { +static const u8 keyblob_keyseeds[][0x10] = { { 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, //1.0.0 { 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, //3.0.0 { 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, //3.0.1 @@ -95,24 +96,12 @@ static const u8 console_keyseed[0x10] = static const u8 key8_keyseed[] = { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 }; -static const u8 master_keyseed_4xx[0x10] = +static const u8 master_keyseed_4xx_5xx[0x10] = { 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 }; -static const u8 console_keyseed_4xx[0x10] = +static const u8 console_keyseed_4xx_5xx[0x10] = { 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 }; -#define CRC32C_POLY 0x82F63B78 -u32 crc32c(const u8 *buf, u32 len) -{ - u32 crc = 0xFFFFFFFF; - while (len--) - { - crc ^= *buf++; - for (int i = 0; i < 8; i++) - crc = (crc & 1) ? (crc >> 1) ^ CRC32C_POLY : crc >> 1; - } - return ~crc; -} static void _se_lock() { @@ -145,23 +134,26 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw) { u8 tmp[0x10]; - se_key_acc_ctrl(0x0D, 0x15); - se_key_acc_ctrl(0x0E, 0x15); + if (kb > KB_FIRMWARE_VERSION_MAX) + return 0; + + se_key_acc_ctrl(13, 0x15); + se_key_acc_ctrl(14, 0x15); //Get TSEC key. if (tsec_query(tmp, 1, tsec_fw) < 0) return 0; - se_aes_key_set(0x0D, tmp, 0x10); + se_aes_key_set(13, tmp, 0x10); //Derive keyblob keys from TSEC+SBK. - se_aes_crypt_block_ecb(0x0D, 0x00, tmp, keyblob_keyseeds[0]); - se_aes_unwrap_key(0x0F, 0x0E, tmp); - se_aes_crypt_block_ecb(0xD, 0x00, tmp, keyblob_keyseeds[kb]); - se_aes_unwrap_key(0x0D, 0x0E, tmp); + se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]); + se_aes_unwrap_key(15, 14, tmp); + se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]); + se_aes_unwrap_key(13, 14, tmp); - // Clear SBK - se_aes_key_clear(0x0E); + //Clear SBK. + se_aes_key_clear(14); //TODO: verify keyblob CMAC. //se_aes_unwrap_key(11, 13, cmac_keyseed); @@ -169,45 +161,42 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw) //if (!memcmp(keyblob, tmp, 0x10)) // return 0; - se_aes_crypt_block_ecb(0x0D, 0, tmp, cmac_keyseed); - se_aes_unwrap_key(0x0B, 0x0D, cmac_keyseed); + se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed); + se_aes_unwrap_key(11, 13, cmac_keyseed); //Decrypt keyblob and set keyslots. - se_aes_crypt_ctr(0x0D, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10); - se_aes_key_set(0x0B, keyblob + 0x20 + 0x80, 0x10); // package1 key - se_aes_key_set(0x0C, keyblob + 0x20, 0x10); - se_aes_key_set(0x0D, keyblob + 0x20, 0x10); + se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10); + se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); //Package1 key. + se_aes_key_set(12, keyblob + 0x20, 0x10); + se_aes_key_set(13, keyblob + 0x20, 0x10); - se_aes_crypt_block_ecb(0x0C, 0, tmp, master_keyseed_retail); + se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail); switch (kb) { case KB_FIRMWARE_VERSION_100_200: case KB_FIRMWARE_VERSION_300: case KB_FIRMWARE_VERSION_301: - se_aes_unwrap_key(0x0D, 0x0F, console_keyseed); - se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail); + se_aes_unwrap_key(13, 15, console_keyseed); + se_aes_unwrap_key(12, 12, master_keyseed_retail); break; - case KB_FIRMWARE_VERSION_400: - se_aes_unwrap_key(0x0D, 0x0F, console_keyseed_4xx); - se_aes_unwrap_key(0x0F, 0x0F, console_keyseed); - se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx); - se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail); + se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx); + se_aes_unwrap_key(15, 15, console_keyseed); + se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx); + se_aes_unwrap_key(12, 12, master_keyseed_retail); break; - case KB_FIRMWARE_VERSION_500: - default: - se_aes_unwrap_key(0x0A, 0x0F, console_keyseed_4xx); - se_aes_unwrap_key(0x0F, 0x0F, console_keyseed); - se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx); - se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail); + se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx); + se_aes_unwrap_key(15, 15, console_keyseed); + se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx); + se_aes_unwrap_key(12, 12, master_keyseed_retail); break; } //Package2 key. - se_key_acc_ctrl(0x08, 0x15); - se_aes_unwrap_key(0x08, 0x0C, key8_keyseed); + se_key_acc_ctrl(8, 0x15); + se_aes_unwrap_key(8, 12, key8_keyseed); return 1; } @@ -385,6 +374,7 @@ int hos_launch(ini_sec_t *cfg) { int bootStateDramPkg2; int bootStatePkg2Continue; + int end_di = 0; launch_ctxt_t ctxt; memset(&ctxt, 0, sizeof(launch_ctxt_t)); @@ -491,24 +481,25 @@ int hos_launch(ini_sec_t *cfg) gfx_printf(&gfx_con, "\n%kBooting...%k\n", 0xFF00FF96, 0xFFCCCCCC); - se_aes_key_clear(0x8); - se_aes_key_clear(0xB); + se_aes_key_clear(8); + se_aes_key_clear(11); switch (ctxt.pkg1_id->kb) { case KB_FIRMWARE_VERSION_100_200: case KB_FIRMWARE_VERSION_300: case KB_FIRMWARE_VERSION_301: - se_key_acc_ctrl(0xC, 0xFF); - se_key_acc_ctrl(0xD, 0xFF); + se_key_acc_ctrl(12, 0xFF); + se_key_acc_ctrl(13, 0xFF); bootStateDramPkg2 = 2; bootStatePkg2Continue = 3; + end_di = 1; break; default: case KB_FIRMWARE_VERSION_400: case KB_FIRMWARE_VERSION_500: - se_key_acc_ctrl(0xC, 0xFF); - se_key_acc_ctrl(0xF, 0xFF); + se_key_acc_ctrl(12, 0xFF); + se_key_acc_ctrl(15, 0xFF); bootStateDramPkg2 = 2; bootStatePkg2Continue = 4; break; @@ -545,8 +536,9 @@ int hos_launch(ini_sec_t *cfg) PMC(0x5BC) = 0xFFFFFFFF; PMC(0x5C0) = 0xFFAAFFFF;*/ - //TODO: Cleanup. - //display_end(); + //Disable display. + if (end_di) + display_end(); //Signal to pkg2 ready and continue boot. *mb_in = bootStatePkg2Continue; diff --git a/ipl/pinmux.h b/ipl/pinmux.h index 14f0ec4..eae897c 100755 --- a/ipl/pinmux.h +++ b/ipl/pinmux.h @@ -41,6 +41,11 @@ #define PINMUX_AUX_DMIC3_CLK 0xB4 #define PINMUX_AUX_UART2_TX 0xF4 #define PINMUX_AUX_UART3_TX 0x104 +#define PINMUX_AUX_NFC_EN 0x1D0 +#define PINMUX_AUX_NFC_INT 0x1D4 +#define PINMUX_AUX_LCD_BL_PWM 0x1FC +#define PINMUX_AUX_LCD_BL_EN 0x200 +#define PINMUX_AUX_LCD_RST 0x204 #define PINMUX_AUX_GPIO_PE6 0x248 #define PINMUX_AUX_GPIO_PH6 0x250 #define PINMUX_AUX_GPIO_PZ1 0x280 diff --git a/ipl/pkg1.c b/ipl/pkg1.c index 9e0300e..7e4565e 100755 --- a/ipl/pkg1.c +++ b/ipl/pkg1.c @@ -16,19 +16,13 @@ #include #include "pkg1.h" +#include "arm64.h" #include "se.h" -#define _ADRP(r, o) 0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F) -#define _MOVZX(r, i, s) 0xD2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F) -#define _MOVKX(r, i, s) 0xF2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F) -#define _BL(a, o) 0x94000000 | (((o) - (a)) >> 2) & 0x3FFFFFF -#define _NOP() 0xD503201F - #define SM_100_ADR 0x4002B020 - PATCHSET_DEF(_secmon_1_patchset, //Patch the relocator to be able to run from SM_100_ADR. - { 0x1E0, _ADRP(0, 0x7C013000 - (SM_100_ADR - 0x40)) }, + { 0x1E0, _ADRP(0, 0x7C013000 - _PAGEOFF(SM_100_ADR)) }, //Patch package2 decryption and signature/hash checks. { 0x9F0 + 0xADC, _NOP() }, //Header signature. { 0x9F0 + 0xB8C, _NOP() }, //Version. diff --git a/ipl/pkg2.c b/ipl/pkg2.c index cd66c94..88a4bca 100755 --- a/ipl/pkg2.c +++ b/ipl/pkg2.c @@ -16,6 +16,7 @@ #include #include "pkg2.h" +#include "arm64.h" #include "heap.h" #include "se.h" @@ -25,9 +26,6 @@ extern gfx_con_t gfx_con; #define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/ #define DPRINTF(...) -#define _MOVZX(r, i, s) 0xD2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F) -#define _NOP() 0xD503201F - // Include kernel patches here, so we can utilize pkg1 id PATCHSET_DEF(_kernel_1_patchset, { 0x3764C, _NOP() }, // Disable SVC verifications diff --git a/ipl/tui.c b/ipl/tui.c index 49874c8..d95e061 100755 --- a/ipl/tui.c +++ b/ipl/tui.c @@ -50,11 +50,11 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu) gfx_con_setpos(con, menu->x, menu->y); gfx_printf(con, "[%s]\n\n", menu->caption); - // Skip caption or seperator lines selection + // Skip caption or seperator lines selection. while (menu->ents[idx].type == MENT_CAPTION || menu->ents[idx].type == MENT_CHGLINE) { - if (prev_idx <= idx || (!idx && prev_idx == cnt - 1)) + if (prev_idx <= idx || (!idx && prev_idx == cnt - 1)) { idx++; if (idx > (cnt - 1)) @@ -75,7 +75,7 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu) } prev_idx = idx; - // Draw the menu + //Draw the menu. for (cnt = 0; menu->ents[cnt].type != MENT_END; cnt++) { if (cnt == idx) diff --git a/ipl/util.c b/ipl/util.c index ef009a1..c060522 100755 --- a/ipl/util.c +++ b/ipl/util.c @@ -35,3 +35,16 @@ void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops) base[ops[i].off] = ops[i].val; } +#define CRC32C_POLY 0x82F63B78 +u32 crc32c(const void *buf, u32 len) +{ + const u8 *cbuf = (const u8 *)buf; + u32 crc = 0xFFFFFFFF; + while (len--) + { + crc ^= *cbuf++; + for (int i = 0; i < 8; i++) + crc = crc & 1 ? (crc >> 1) ^ CRC32C_POLY : crc >> 1; + } + return ~crc; +} diff --git a/ipl/util.h b/ipl/util.h index a1fc7dd..8377446 100755 --- a/ipl/util.h +++ b/ipl/util.h @@ -28,5 +28,6 @@ typedef struct _cfg_op_t u32 get_tmr(); void sleep(u32 ticks); void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); +u32 crc32c(const void *buf, u32 len); #endif