Merge interim hekate bugfixes
This commit is contained in:
parent
04d989a345
commit
e1ffda6ab9
|
@ -142,7 +142,7 @@ void display_backlight_pwm_init()
|
||||||
{
|
{
|
||||||
clock_enable_pwm();
|
clock_enable_pwm();
|
||||||
|
|
||||||
PWM(PWM_CONTROLLER_PWM_CSR) = (1 << 31); // Enable PWM
|
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31); // Enable PWM
|
||||||
|
|
||||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; // PWM clock source.
|
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; // PWM clock source.
|
||||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode.
|
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode.
|
||||||
|
@ -156,7 +156,7 @@ void display_backlight(bool enable)
|
||||||
|
|
||||||
void display_backlight_brightness(u32 brightness, u32 step_delay)
|
void display_backlight_brightness(u32 brightness, u32 step_delay)
|
||||||
{
|
{
|
||||||
u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR) >> 16) & 0xFF;
|
u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF;
|
||||||
if (brightness == old_value)
|
if (brightness == old_value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
|
||||||
{
|
{
|
||||||
for (u32 i = old_value; i < brightness + 1; i++)
|
for (u32 i = old_value; i < brightness + 1; i++)
|
||||||
{
|
{
|
||||||
PWM(PWM_CONTROLLER_PWM_CSR) = (1 << 31) | (i << 16); // Enable PWM
|
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31) | (i << 16); // Enable PWM
|
||||||
usleep(step_delay);
|
usleep(step_delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,12 +175,12 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
|
||||||
{
|
{
|
||||||
for (u32 i = old_value; i > brightness; i--)
|
for (u32 i = old_value; i > brightness; i--)
|
||||||
{
|
{
|
||||||
PWM(PWM_CONTROLLER_PWM_CSR) = (1 << 31) | (i << 16); // Enable PWM
|
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31) | (i << 16); // Enable PWM
|
||||||
usleep(step_delay);
|
usleep(step_delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!brightness)
|
if (!brightness)
|
||||||
PWM(PWM_CONTROLLER_PWM_CSR) = 0;
|
PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_end()
|
void display_end()
|
||||||
|
|
|
@ -350,9 +350,6 @@
|
||||||
|
|
||||||
#define MIPI_CAL_MIPI_BIAS_PAD_CFG2 0x60
|
#define MIPI_CAL_MIPI_BIAS_PAD_CFG2 0x60
|
||||||
|
|
||||||
/*! Display backlight related PWM registers. */
|
|
||||||
#define PWM_CONTROLLER_PWM_CSR 0x00
|
|
||||||
|
|
||||||
void display_init();
|
void display_init();
|
||||||
void display_backlight_pwm_init();
|
void display_backlight_pwm_init();
|
||||||
void display_end();
|
void display_end();
|
||||||
|
|
236
source/gfx/gfx.c
236
source/gfx/gfx.c
|
@ -118,73 +118,73 @@ static const u8 _gfx_font[] = {
|
||||||
0x00, 0x00, 0x00, 0x4C, 0x32, 0x00, 0x00, 0x00 // Char 126 (~)
|
0x00, 0x00, 0x00, 0x4C, 0x32, 0x00, 0x00, 0x00 // Char 126 (~)
|
||||||
};
|
};
|
||||||
|
|
||||||
void gfx_init_ctxt(gfx_ctxt_t *ctxt, u32 *fb, u32 width, u32 height, u32 stride)
|
void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride)
|
||||||
{
|
{
|
||||||
ctxt->fb = fb;
|
gfx_ctxt.fb = fb;
|
||||||
ctxt->width = width;
|
gfx_ctxt.width = width;
|
||||||
ctxt->height = height;
|
gfx_ctxt.height = height;
|
||||||
ctxt->stride = stride;
|
gfx_ctxt.stride = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_clear_grey(gfx_ctxt_t *ctxt, u8 color)
|
void gfx_clear_grey(u8 color)
|
||||||
{
|
{
|
||||||
memset(ctxt->fb, color, 0x3C0000);
|
memset(gfx_ctxt.fb, color, 0x3C0000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_clear_color(gfx_ctxt_t *ctxt, u32 color)
|
void gfx_clear_color(u32 color)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < ctxt->height * ctxt->stride; i++)
|
for (u32 i = 0; i < gfx_ctxt.height * gfx_ctxt.stride; i++)
|
||||||
ctxt->fb[i] = color;
|
gfx_ctxt.fb[i] = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_clear_partial_grey(gfx_ctxt_t *ctxt, u8 color, u32 pos_x, u32 height)
|
void gfx_clear_partial_grey(u8 color, u32 pos_x, u32 height)
|
||||||
{
|
{
|
||||||
memset(ctxt->fb + pos_x * ctxt->stride, color, height * 4 * ctxt->stride);
|
memset(gfx_ctxt.fb + pos_x * gfx_ctxt.stride, color, height * 4 * gfx_ctxt.stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt)
|
void gfx_con_init()
|
||||||
{
|
{
|
||||||
con->gfx_ctxt = ctxt;
|
gfx_con.gfx_ctxt = &gfx_ctxt;
|
||||||
con->fntsz = 16;
|
gfx_con.fntsz = 16;
|
||||||
con->x = 0;
|
gfx_con.x = 0;
|
||||||
con->y = 0;
|
gfx_con.y = 0;
|
||||||
con->savedx = 0;
|
gfx_con.savedx = 0;
|
||||||
con->savedy = 0;
|
gfx_con.savedy = 0;
|
||||||
con->fgcol = 0xFFCCCCCC;
|
gfx_con.fgcol = 0xFFCCCCCC;
|
||||||
con->fillbg = 0;
|
gfx_con.fillbg = 1;
|
||||||
con->bgcol = 0xFF1B1B1B;
|
gfx_con.bgcol = 0xFF1B1B1B;
|
||||||
con->mute = 0;
|
gfx_con.mute = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_con_setcol(gfx_con_t *con, u32 fgcol, int fillbg, u32 bgcol)
|
void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol)
|
||||||
{
|
{
|
||||||
con->fgcol = fgcol;
|
gfx_con.fgcol = fgcol;
|
||||||
con->fillbg = fillbg;
|
gfx_con.fillbg = fillbg;
|
||||||
con->bgcol = bgcol;
|
gfx_con.bgcol = bgcol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_con_getpos(gfx_con_t *con, u32 *x, u32 *y)
|
void gfx_con_getpos(u32 *x, u32 *y)
|
||||||
{
|
{
|
||||||
*x = con->x;
|
*x = gfx_con.x;
|
||||||
*y = con->y;
|
*y = gfx_con.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_con_setpos(gfx_con_t *con, u32 x, u32 y)
|
void gfx_con_setpos(u32 x, u32 y)
|
||||||
{
|
{
|
||||||
con->x = x;
|
gfx_con.x = x;
|
||||||
con->y = y;
|
gfx_con.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_putc(gfx_con_t *con, char c)
|
void gfx_putc(char c)
|
||||||
{
|
{
|
||||||
// Duplicate code for performance reasons.
|
// Duplicate code for performance reasons.
|
||||||
switch (con->fntsz)
|
switch (gfx_con.fntsz)
|
||||||
{
|
{
|
||||||
case 16:
|
case 16:
|
||||||
if (c >= 32 && c <= 126)
|
if (c >= 32 && c <= 126)
|
||||||
{
|
{
|
||||||
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
|
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
|
||||||
u32 *fb = con->gfx_ctxt->fb + con->x + con->y * con->gfx_ctxt->stride;
|
u32 *fb = gfx_ctxt.fb + gfx_con.x + gfx_con.y * gfx_ctxt.stride;
|
||||||
|
|
||||||
for (u32 i = 0; i < 16; i+=2)
|
for (u32 i = 0; i < 16; i+=2)
|
||||||
{
|
{
|
||||||
|
@ -195,37 +195,37 @@ void gfx_putc(gfx_con_t *con, char c)
|
||||||
{
|
{
|
||||||
if (v & 1)
|
if (v & 1)
|
||||||
{
|
{
|
||||||
*fb = con->fgcol;
|
*fb = gfx_con.fgcol;
|
||||||
fb++;
|
fb++;
|
||||||
*fb = con->fgcol;
|
*fb = gfx_con.fgcol;
|
||||||
}
|
}
|
||||||
else if (con->fillbg)
|
else if (gfx_con.fillbg)
|
||||||
{
|
{
|
||||||
*fb = con->bgcol;
|
*fb = gfx_con.bgcol;
|
||||||
fb++;
|
fb++;
|
||||||
*fb = con->bgcol;
|
*fb = gfx_con.bgcol;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fb++;
|
fb++;
|
||||||
v >>= 1;
|
v >>= 1;
|
||||||
fb++;
|
fb++;
|
||||||
}
|
}
|
||||||
fb += con->gfx_ctxt->stride - 16;
|
fb += gfx_ctxt.stride - 16;
|
||||||
v = *cbuf;
|
v = *cbuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
con->x += 16;
|
gfx_con.x += 16;
|
||||||
if (con->x >= con->gfx_ctxt->width - 16) {
|
if (gfx_con.x >= gfx_ctxt.width - 16) {
|
||||||
con->x = 0;
|
gfx_con.x = 0;
|
||||||
con->y += 16;
|
gfx_con.y += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == '\n')
|
else if (c == '\n')
|
||||||
{
|
{
|
||||||
con->x = 0;
|
gfx_con.x = 0;
|
||||||
con->y += 16;
|
gfx_con.y +=16;
|
||||||
if (con->y > con->gfx_ctxt->height - 16)
|
if (gfx_con.y > gfx_ctxt.height - 16)
|
||||||
con->y = 0;
|
gfx_con.y = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -233,49 +233,49 @@ void gfx_putc(gfx_con_t *con, char c)
|
||||||
if (c >= 32 && c <= 126)
|
if (c >= 32 && c <= 126)
|
||||||
{
|
{
|
||||||
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
|
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
|
||||||
u32 *fb = con->gfx_ctxt->fb + con->x + con->y * con->gfx_ctxt->stride;
|
u32 *fb = gfx_ctxt.fb + gfx_con.x + gfx_con.y * gfx_ctxt.stride;
|
||||||
for (u32 i = 0; i < 8; i++)
|
for (u32 i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
u8 v = *cbuf++;
|
u8 v = *cbuf++;
|
||||||
for (u32 j = 0; j < 8; j++)
|
for (u32 j = 0; j < 8; j++)
|
||||||
{
|
{
|
||||||
if (v & 1)
|
if (v & 1)
|
||||||
*fb = con->fgcol;
|
*fb = gfx_con.fgcol;
|
||||||
else if (con->fillbg)
|
else if (gfx_con.fillbg)
|
||||||
*fb = con->bgcol;
|
*fb = gfx_con.bgcol;
|
||||||
v >>= 1;
|
v >>= 1;
|
||||||
fb++;
|
fb++;
|
||||||
}
|
}
|
||||||
fb += con->gfx_ctxt->stride - 8;
|
fb += gfx_ctxt.stride - 8;
|
||||||
}
|
}
|
||||||
con->x += 8;
|
gfx_con.x += 8;
|
||||||
if (con->x >= con->gfx_ctxt->width - 8) {
|
if (gfx_con.x >= gfx_ctxt.width - 8) {
|
||||||
con->x = 0;
|
gfx_con.x = 0;
|
||||||
con->y += 8;
|
gfx_con.y += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == '\n')
|
else if (c == '\n')
|
||||||
{
|
{
|
||||||
con->x = 0;
|
gfx_con.x = 0;
|
||||||
con->y += 8;
|
gfx_con.y += 8;
|
||||||
if (con->y > con->gfx_ctxt->height - 8)
|
if (gfx_con.y > gfx_ctxt.height - 8)
|
||||||
con->y = 0;
|
gfx_con.y = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_puts(gfx_con_t *con, const char *s)
|
void gfx_puts(const char *s)
|
||||||
{
|
{
|
||||||
if (!s || con->mute)
|
if (!s || gfx_con.mute)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (; *s; s++)
|
for (; *s; s++)
|
||||||
gfx_putc(con, *s);
|
gfx_putc(*s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _gfx_putn(gfx_con_t *con, u32 v, int base, char fill, int fcnt)
|
static void _gfx_putn(u32 v, int base, char fill, int fcnt)
|
||||||
{
|
{
|
||||||
char buf[65];
|
char buf[65];
|
||||||
static const char digits[] = "0123456789ABCDEFghijklmnopqrstuvwxyz";
|
static const char digits[] = "0123456789ABCDEFghijklmnopqrstuvwxyz";
|
||||||
|
@ -303,28 +303,28 @@ static void _gfx_putn(gfx_con_t *con, u32 v, int base, char fill, int fcnt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx_puts(con, p);
|
gfx_puts(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_put_small_sep(gfx_con_t *con)
|
void gfx_put_small_sep(gfx_con_t *con)
|
||||||
{
|
{
|
||||||
u8 prevFontSize = con->fntsz;
|
u8 prevFontSize = gfx_con.fntsz;
|
||||||
con->fntsz = 8;
|
gfx_con.fntsz = 8;
|
||||||
gfx_putc(con, '\n');
|
gfx_putc('\n');
|
||||||
con->fntsz = prevFontSize;
|
gfx_con.fntsz = prevFontSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_put_big_sep(gfx_con_t *con)
|
void gfx_put_big_sep(gfx_con_t *con)
|
||||||
{
|
{
|
||||||
u8 prevFontSize = con->fntsz;
|
u8 prevFontSize = gfx_con.fntsz;
|
||||||
con->fntsz = 16;
|
gfx_con.fntsz = 16;
|
||||||
gfx_putc(con, '\n');
|
gfx_putc('\n');
|
||||||
con->fntsz = prevFontSize;
|
gfx_con.fntsz = prevFontSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_printf(gfx_con_t *con, const char *fmt, ...)
|
void gfx_printf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
if (con->mute)
|
if (gfx_con.mute)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -357,40 +357,40 @@ void gfx_printf(gfx_con_t *con, const char *fmt, ...)
|
||||||
switch(*fmt)
|
switch(*fmt)
|
||||||
{
|
{
|
||||||
case 'c':
|
case 'c':
|
||||||
gfx_putc(con, va_arg(ap, u32));
|
gfx_putc(va_arg(ap, u32));
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
gfx_puts(con, va_arg(ap, char *));
|
gfx_puts(va_arg(ap, char *));
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
_gfx_putn(con, va_arg(ap, u32), 10, fill, fcnt);
|
_gfx_putn(va_arg(ap, u32), 10, fill, fcnt);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'P':
|
case 'P':
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
_gfx_putn(con, va_arg(ap, u32), 16, fill, fcnt);
|
_gfx_putn(va_arg(ap, u32), 16, fill, fcnt);
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
con->fgcol = va_arg(ap, u32);
|
gfx_con.fgcol = va_arg(ap, u32);
|
||||||
break;
|
break;
|
||||||
case 'K':
|
case 'K':
|
||||||
con->bgcol = va_arg(ap, u32);
|
gfx_con.bgcol = va_arg(ap, u32);
|
||||||
con->fillbg = 1;
|
gfx_con.fillbg = 1;
|
||||||
break;
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
gfx_putc(con, '%');
|
gfx_putc('%');
|
||||||
break;
|
break;
|
||||||
case '\0':
|
case '\0':
|
||||||
goto out;
|
goto out;
|
||||||
default:
|
default:
|
||||||
gfx_putc(con, '%');
|
gfx_putc('%');
|
||||||
gfx_putc(con, *fmt);
|
gfx_putc(*fmt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gfx_putc(con, *fmt);
|
gfx_putc(*fmt);
|
||||||
fmt++;
|
fmt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,33 +398,33 @@ void gfx_printf(gfx_con_t *con, const char *fmt, ...)
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len)
|
void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||||
{
|
{
|
||||||
if (con->mute)
|
if (gfx_con.mute)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u8 prevFontSize = con->fntsz;
|
u8 prevFontSize = gfx_con.fntsz;
|
||||||
con->fntsz = 8;
|
gfx_con.fntsz = 8;
|
||||||
for(u32 i = 0; i < len; i++)
|
for(u32 i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
if(i % 0x10 == 0)
|
if(i % 0x10 == 0)
|
||||||
{
|
{
|
||||||
if(i != 0)
|
if(i != 0)
|
||||||
{
|
{
|
||||||
gfx_puts(con, "| ");
|
gfx_puts("| ");
|
||||||
for(u32 j = 0; j < 0x10; j++)
|
for(u32 j = 0; j < 0x10; j++)
|
||||||
{
|
{
|
||||||
u8 c = buf[i - 0x10 + j];
|
u8 c = buf[i - 0x10 + j];
|
||||||
if(c >= 32 && c <= 126)
|
if(c >= 32 && c <= 126)
|
||||||
gfx_putc(con, c);
|
gfx_putc(c);
|
||||||
else
|
else
|
||||||
gfx_putc(con, '.');
|
gfx_putc('.');
|
||||||
}
|
}
|
||||||
gfx_putc(con, '\n');
|
gfx_putc('\n');
|
||||||
}
|
}
|
||||||
gfx_printf(con, "%08x: ", base + i);
|
gfx_printf("%08x: ", base + i);
|
||||||
}
|
}
|
||||||
gfx_printf(con, "%02x ", buf[i]);
|
gfx_printf("%02x ", buf[i]);
|
||||||
if (i == len - 1)
|
if (i == len - 1)
|
||||||
{
|
{
|
||||||
int ln = len % 0x10 != 0;
|
int ln = len % 0x10 != 0;
|
||||||
|
@ -433,22 +433,22 @@ void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len)
|
||||||
{
|
{
|
||||||
k = (len & 0xF) - 1;
|
k = (len & 0xF) - 1;
|
||||||
for (u32 j = 0; j < 0x10 - k; j++)
|
for (u32 j = 0; j < 0x10 - k; j++)
|
||||||
gfx_puts(con, " ");
|
gfx_puts(" ");
|
||||||
}
|
}
|
||||||
gfx_puts(con, "| ");
|
gfx_puts("| ");
|
||||||
for(u32 j = 0; j < (ln ? k : k + 1); j++)
|
for(u32 j = 0; j < (ln ? k : k + 1); j++)
|
||||||
{
|
{
|
||||||
u8 c = buf[i - k + j];
|
u8 c = buf[i - k + j];
|
||||||
if(c >= 32 && c <= 126)
|
if(c >= 32 && c <= 126)
|
||||||
gfx_putc(con, c);
|
gfx_putc(c);
|
||||||
else
|
else
|
||||||
gfx_putc(con, '.');
|
gfx_putc('.');
|
||||||
}
|
}
|
||||||
gfx_putc(con, '\n');
|
gfx_putc('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gfx_putc(con, '\n');
|
gfx_putc('\n');
|
||||||
con->fntsz = prevFontSize;
|
gfx_con.fntsz = prevFontSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int abs(int x)
|
static int abs(int x)
|
||||||
|
@ -458,12 +458,12 @@ static int abs(int x)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_set_pixel(gfx_ctxt_t *ctxt, u32 x, u32 y, u32 color)
|
void gfx_set_pixel(u32 x, u32 y, u32 color)
|
||||||
{
|
{
|
||||||
ctxt->fb[x + y * ctxt->stride] = color;
|
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color)
|
void gfx_line(int x0, int y0, int x1, int y1, u32 color)
|
||||||
{
|
{
|
||||||
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
||||||
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
||||||
|
@ -471,7 +471,7 @@ void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color)
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
gfx_set_pixel(ctxt, x0, y0, color);
|
gfx_set_pixel(x0, y0, color);
|
||||||
if (x0 == x1 && y0 == y1)
|
if (x0 == x1 && y0 == y1)
|
||||||
break;
|
break;
|
||||||
e2 = err;
|
e2 = err;
|
||||||
|
@ -488,46 +488,46 @@ void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_set_rect_grey(gfx_ctxt_t *ctxt, const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
void gfx_set_rect_grey(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||||
{
|
{
|
||||||
u32 pos = 0;
|
u32 pos = 0;
|
||||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||||
{
|
{
|
||||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||||
{
|
{
|
||||||
memset(&ctxt->fb[x + y*ctxt->stride], buf[pos], 4);
|
memset(&gfx_ctxt.fb[x + y*gfx_ctxt.stride], buf[pos], 4);
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void gfx_set_rect_rgb(gfx_ctxt_t *ctxt, const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
void gfx_set_rect_rgb(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||||
{
|
{
|
||||||
u32 pos = 0;
|
u32 pos = 0;
|
||||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||||
{
|
{
|
||||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||||
{
|
{
|
||||||
ctxt->fb[x + y*ctxt->stride] = buf[pos + 2] | (buf[pos + 1] << 8) | (buf[pos] << 16);
|
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = buf[pos + 2] | (buf[pos + 1] << 8) | (buf[pos] << 16);
|
||||||
pos+=3;
|
pos+=3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_set_rect_argb(gfx_ctxt_t *ctxt, const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||||
{
|
{
|
||||||
u32 *ptr = (u32 *)buf;
|
u32 *ptr = (u32 *)buf;
|
||||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||||
ctxt->fb[x + y * ctxt->stride] = *ptr++;
|
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = *ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx_render_bmp_argb(gfx_ctxt_t *ctxt, const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||||
{
|
{
|
||||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||||
{
|
{
|
||||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||||
ctxt->fb[x + y * ctxt->stride] = buf[(size_y + pos_y - 1 - y ) * size_x + x - pos_x];
|
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = buf[(size_y + pos_y - 1 - y ) * size_x + x - pos_x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,32 +21,32 @@
|
||||||
|
|
||||||
#include "../../common/common_gfx.h"
|
#include "../../common/common_gfx.h"
|
||||||
|
|
||||||
#define EPRINTF(text) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFF0000, 0xFFCCCCCC)
|
#define EPRINTF(text) gfx_printf("%k"text"%k\n", 0xFFFF0000, 0xFFCCCCCC)
|
||||||
#define EPRINTFARGS(text, args...) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC)
|
#define EPRINTFARGS(text, args...) gfx_printf("%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC)
|
||||||
#define WPRINTF(text) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFFDD00, 0xFFCCCCCC)
|
#define WPRINTF(text) gfx_printf("%k"text"%k\n", 0xFFFFDD00, 0xFFCCCCCC)
|
||||||
#define WPRINTFARGS(text, args...) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFFDD00, args, 0xFFCCCCCC)
|
#define WPRINTFARGS(text, args...) gfx_printf("%k"text"%k\n", 0xFFFFDD00, args, 0xFFCCCCCC)
|
||||||
|
|
||||||
void gfx_init_ctxt(gfx_ctxt_t *ctxt, u32 *fb, u32 width, u32 height, u32 stride);
|
void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride);
|
||||||
void gfx_clear_grey(gfx_ctxt_t *ctxt, u8 color);
|
void gfx_clear_grey(u8 color);
|
||||||
void gfx_clear_partial_grey(gfx_ctxt_t *ctxt, u8 color, u32 pos_x, u32 height);
|
void gfx_clear_partial_grey(u8 color, u32 pos_x, u32 height);
|
||||||
void gfx_clear_color(gfx_ctxt_t *ctxt, u32 color);
|
void gfx_clear_color(u32 color);
|
||||||
void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt);
|
void gfx_con_init();
|
||||||
void gfx_con_setcol(gfx_con_t *con, u32 fgcol, int fillbg, u32 bgcol);
|
void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol);
|
||||||
void gfx_con_getpos(gfx_con_t *con, u32 *x, u32 *y);
|
void gfx_con_getpos(u32 *x, u32 *y);
|
||||||
void gfx_con_setpos(gfx_con_t *con, u32 x, u32 y);
|
void gfx_con_setpos(u32 x, u32 y);
|
||||||
void gfx_putc(gfx_con_t *con, char c);
|
void gfx_putc(char c);
|
||||||
void gfx_puts(gfx_con_t *con, const char *s);
|
void gfx_puts(const char *s);
|
||||||
void gfx_printf(gfx_con_t *con, const char *fmt, ...);
|
void gfx_printf(const char *fmt, ...);
|
||||||
void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len);
|
void gfx_hexdump(u32 base, const u8 *buf, u32 len);
|
||||||
|
|
||||||
void gfx_set_pixel(gfx_ctxt_t *ctxt, u32 x, u32 y, u32 color);
|
void gfx_set_pixel(u32 x, u32 y, u32 color);
|
||||||
void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color);
|
void gfx_line(int x0, int y0, int x1, int y1, u32 color);
|
||||||
void gfx_put_small_sep(gfx_con_t *con);
|
void gfx_put_small_sep(gfx_con_t *con);
|
||||||
void gfx_put_big_sep(gfx_con_t *con);
|
void gfx_put_big_sep(gfx_con_t *con);
|
||||||
void gfx_set_rect_grey(gfx_ctxt_t *ctxt, const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
void gfx_set_rect_grey(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||||
void gfx_set_rect_rgb(gfx_ctxt_t *ctxt, const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
void gfx_set_rect_rgb(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||||
void gfx_set_rect_argb(gfx_ctxt_t *ctxt, const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||||
void gfx_render_bmp_argb(gfx_ctxt_t *ctxt, const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||||
|
|
||||||
// Global gfx console and context.
|
// Global gfx console and context.
|
||||||
gfx_ctxt_t gfx_ctxt;
|
gfx_ctxt_t gfx_ctxt;
|
||||||
|
|
|
@ -22,34 +22,18 @@
|
||||||
#include "pkg1.h"
|
#include "pkg1.h"
|
||||||
#include "../sec/se.h"
|
#include "../sec/se.h"
|
||||||
|
|
||||||
#define SM_100_ADR 0x4002B020
|
|
||||||
|
|
||||||
/*
|
|
||||||
* package1.1 header: <wb, ldr, sm>
|
|
||||||
* package1.1 layout:
|
|
||||||
* 1.0: {sm, ldr, wb} { 2, 1, 0 }
|
|
||||||
* 2.0: {wb, ldr, sm} { 0, 1, 2 }
|
|
||||||
* 3.0: {wb, ldr, sm} { 0, 1, 2 }
|
|
||||||
* 3.1: {wb, ldr, sm} { 0, 1, 2 }
|
|
||||||
* 4.0: {ldr, sm, wb} { 1, 2, 0 }
|
|
||||||
* 5.0: {ldr, sm, wb} { 1, 2, 0 }
|
|
||||||
* 6.0: {ldr, sm, wb} { 1, 2, 0 }
|
|
||||||
* 6.2: {ldr, sm, wb} { 1, 2, 0 }
|
|
||||||
* 7.0: {ldr, sm, wb} { 1, 2, 0 }
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const pkg1_id_t _pkg1_ids[] = {
|
static const pkg1_id_t _pkg1_ids[] = {
|
||||||
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, true, NULL, NULL }, //1.0.0
|
{ "20161121183008", 0, 0x1900, 0x3FE0, 0x4002B020 }, //1.0.0
|
||||||
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, NULL, NULL }, //2.0.0 - 2.3.0
|
{ "20170210155124", 0, 0x1900, 0x3FE0, 0x4002D000 }, //2.0.0 - 2.3.0
|
||||||
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, NULL, NULL }, //3.0.0
|
{ "20170519101410", 1, 0x1A00, 0x3FE0, 0x4002D000 }, //3.0.0
|
||||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, NULL, NULL }, //3.0.1 - 3.0.2
|
{ "20170710161758", 2, 0x1A00, 0x3FE0, 0x4002D000 }, //3.0.1 - 3.0.2
|
||||||
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, NULL, NULL }, //4.0.0 - 4.1.0
|
{ "20170921172629", 3, 0x1800, 0x3FE0, 0x4002B000 }, //4.0.0 - 4.1.0
|
||||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, NULL, NULL }, //5.0.0 - 5.1.0
|
{ "20180220163747", 4, 0x1900, 0x3FE0, 0x4002B000 }, //5.0.0 - 5.1.0
|
||||||
{ "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, NULL, NULL }, //6.0.0 - 6.1.0
|
{ "20180802162753", 5, 0x1900, 0x3FE0, 0x4002B000 }, //6.0.0 - 6.1.0
|
||||||
{ "20181107105733", 6, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, NULL, NULL }, //6.2.0
|
{ "20181107105733", 6, 0x0E00, 0x6FE0, 0x4002B000 }, //6.2.0
|
||||||
{ "20181218175730", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //7.0.0
|
{ "20181218175730", 7, 0x0F00, 0x6FE0, 0x40030000 }, //7.0.0
|
||||||
{ "20190208150037", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //7.0.1
|
{ "20190208150037", 7, 0x0F00, 0x6FE0, 0x40030000 }, //7.0.1
|
||||||
{ "20190314172056", 7, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //8.0.0
|
{ "20190314172056", 7, 0x0E00, 0x6FE0, 0x40030000 }, //8.0.0
|
||||||
{ NULL } //End.
|
{ NULL } //End.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,7 @@ typedef struct _pkg1_id_t
|
||||||
u32 kb;
|
u32 kb;
|
||||||
u32 tsec_off;
|
u32 tsec_off;
|
||||||
u32 pkg11_off;
|
u32 pkg11_off;
|
||||||
u32 sec_map[3];
|
|
||||||
u32 secmon_base;
|
u32 secmon_base;
|
||||||
u32 warmboot_base;
|
|
||||||
bool set_warmboot;
|
|
||||||
u32 *secmon_patchset;
|
|
||||||
u32 *warmboot_patchset;
|
|
||||||
} pkg1_id_t;
|
} pkg1_id_t;
|
||||||
|
|
||||||
const pkg1_id_t *pkg1_identify(u8 *pkg1);
|
const pkg1_id_t *pkg1_identify(u8 *pkg1);
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "../gfx/gfx.h"
|
#include "../gfx/gfx.h"
|
||||||
|
|
||||||
/*#include "util.h"
|
/*#include "util.h"
|
||||||
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
|
#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||||
#define DEBUG_PRINTING*/
|
#define DEBUG_PRINTING*/
|
||||||
#define DPRINTF(...)
|
#define DPRINTF(...)
|
||||||
|
|
||||||
|
@ -103,10 +103,10 @@ int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp)
|
||||||
|
|
||||||
unsigned int compSize = hdr.sections[sectIdx].size_comp;
|
unsigned int compSize = hdr.sections[sectIdx].size_comp;
|
||||||
unsigned int outputSize = hdr.sections[sectIdx].size_decomp;
|
unsigned int outputSize = hdr.sections[sectIdx].size_decomp;
|
||||||
//gfx_printf(&gfx_con, "Decomping %s KIP1 sect %d of size %d...\n", (const char*)hdr.name, sectIdx, compSize);
|
//gfx_printf("Decomping %s KIP1 sect %d of size %d...\n", (const char*)hdr.name, sectIdx, compSize);
|
||||||
if (blz_uncompress_srcdest(srcDataPtr, compSize, dstDataPtr, outputSize) == 0)
|
if (blz_uncompress_srcdest(srcDataPtr, compSize, dstDataPtr, outputSize) == 0)
|
||||||
{
|
{
|
||||||
gfx_printf(&gfx_con, "%kERROR decomping sect %d of %s KIP!%k\n", 0xFFFF0000, sectIdx, (char*)hdr.name, 0xFFCCCCCC);
|
gfx_printf("%kERROR decomping sect %d of %s KIP!%k\n", 0xFFFF0000, sectIdx, (char*)hdr.name, 0xFFCCCCCC);
|
||||||
free(newKip);
|
free(newKip);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -145,7 +145,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data)
|
||||||
|
|
||||||
// Decrypt header.
|
// Decrypt header.
|
||||||
se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
|
se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
|
||||||
//gfx_hexdump(&gfx_con, (u32)hdr, hdr, 0x100);
|
//gfx_hexdump((u32)hdr, hdr, 0x100);
|
||||||
|
|
||||||
if (hdr->magic != PKG2_MAGIC)
|
if (hdr->magic != PKG2_MAGIC)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -157,7 +157,7 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
se_aes_crypt_ctr(8, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
|
se_aes_crypt_ctr(8, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
|
||||||
//gfx_hexdump(&gfx_con, (u32)pdata, pdata, 0x100);
|
//gfx_hexdump((u32)pdata, pdata, 0x100);
|
||||||
|
|
||||||
pdata += hdr->sec_size[i];
|
pdata += hdr->sec_size[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,20 +26,6 @@
|
||||||
#define PKG2_SEC_KERNEL 0
|
#define PKG2_SEC_KERNEL 0
|
||||||
#define PKG2_SEC_INI1 1
|
#define PKG2_SEC_INI1 1
|
||||||
|
|
||||||
#define INI1_MAGIC 0x31494E49
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
// Always applied.
|
|
||||||
SVC_GENERIC = 0,
|
|
||||||
// Generic instruction patches.
|
|
||||||
SVC_VERIFY_DS = 0x10,
|
|
||||||
DEBUG_MODE_EN,
|
|
||||||
ATM_GEN_PATCH,
|
|
||||||
// >4 bytes patches. Value is a pointer of a u32 array.
|
|
||||||
ATM_ARR_PATCH,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _pkg2_hdr_t
|
typedef struct _pkg2_hdr_t
|
||||||
{
|
{
|
||||||
u8 ctr[0x10];
|
u8 ctr[0x10];
|
||||||
|
|
|
@ -55,7 +55,7 @@ u8 warmboot_reboot[] = {
|
||||||
#define SEPT_STG2_ADDR (SEPT_PK1T_ADDR + 0x60E0)
|
#define SEPT_STG2_ADDR (SEPT_PK1T_ADDR + 0x60E0)
|
||||||
#define SEPT_PKG_SZ (0x2F100 + WB_RST_SIZE)
|
#define SEPT_PKG_SZ (0x2F100 + WB_RST_SIZE)
|
||||||
|
|
||||||
extern boot_cfg_t *b_cfg;
|
extern boot_cfg_t b_cfg;
|
||||||
extern void sd_unmount();
|
extern void sd_unmount();
|
||||||
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
|
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ int reboot_to_sept(const u8 *tsec_fw)
|
||||||
|
|
||||||
// Save auto boot config to payload, if any.
|
// Save auto boot config to payload, if any.
|
||||||
boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t));
|
boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t));
|
||||||
memcpy(tmp_cfg, b_cfg, sizeof(boot_cfg_t));
|
memcpy(tmp_cfg, &b_cfg, sizeof(boot_cfg_t));
|
||||||
|
|
||||||
tmp_cfg->boot_cfg |= BOOT_CFG_SEPT_RUN;
|
tmp_cfg->boot_cfg |= BOOT_CFG_SEPT_RUN;
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ int reboot_to_sept(const u8 *tsec_fw)
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
|
|
||||||
sd_unmount();
|
sd_unmount();
|
||||||
gfx_printf(&gfx_con, "\n%kPress Power or Vol +/-\n%k to Reboot to Sept...", COLOR_BLUE, COLOR_VIOLET);
|
gfx_printf("\n%kPress Power or Vol +/-\n%k to Reboot to Sept...", COLOR_BLUE, COLOR_VIOLET);
|
||||||
btn_wait();
|
btn_wait();
|
||||||
|
|
||||||
u32 pk1t_sept = SEPT_PK1T_ADDR - (ALIGN(PATCHED_RELOC_SZ, 0x10) + WB_RST_SIZE);
|
u32 pk1t_sept = SEPT_PK1T_ADDR - (ALIGN(PATCHED_RELOC_SZ, 0x10) + WB_RST_SIZE);
|
||||||
|
|
|
@ -52,10 +52,10 @@ emmc_part_t *system_part;
|
||||||
|
|
||||||
#define TPRINTF(text) \
|
#define TPRINTF(text) \
|
||||||
end_time = get_tmr_ms(); \
|
end_time = get_tmr_ms(); \
|
||||||
gfx_printf(&gfx_con, text" done @ %d.%03ds\n", (end_time - start_time) / 1000, (end_time - start_time) % 1000)
|
gfx_printf(text" done @ %d.%03ds\n", (end_time - start_time) / 1000, (end_time - start_time) % 1000)
|
||||||
#define TPRINTFARGS(text, args...) \
|
#define TPRINTFARGS(text, args...) \
|
||||||
end_time = get_tmr_ms(); \
|
end_time = get_tmr_ms(); \
|
||||||
gfx_printf(&gfx_con, text" done @ %d.%03ds\n", args, (end_time - start_time) / 1000, (end_time - start_time) % 1000)
|
gfx_printf(text" done @ %d.%03ds\n", args, (end_time - start_time) / 1000, (end_time - start_time) % 1000)
|
||||||
#define SAVE_KEY(name, src, len) _save_key(name, src, len, text_buffer, &buf_index)
|
#define SAVE_KEY(name, src, len) _save_key(name, src, len, text_buffer, &buf_index)
|
||||||
#define SAVE_KEY_FAMILY(name, src, count, len) _save_key_family(name, src, count, len, text_buffer, &buf_index)
|
#define SAVE_KEY_FAMILY(name, src, count, len) _save_key_family(name, src, count, len, text_buffer, &buf_index)
|
||||||
|
|
||||||
|
@ -227,10 +227,10 @@ static u32 _sprintf(char *buffer, const char *fmt, ...);
|
||||||
|
|
||||||
void dump_keys() {
|
void dump_keys() {
|
||||||
display_backlight_brightness(100, 1000);
|
display_backlight_brightness(100, 1000);
|
||||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1280);
|
gfx_clear_partial_grey(0x1B, 0, 1280);
|
||||||
gfx_con_setpos(&gfx_con, 0, 0);
|
gfx_con_setpos(0, 0);
|
||||||
|
|
||||||
gfx_printf(&gfx_con, "[%kLo%kck%kpi%kck%k-R%kCM%k v%d.%d%k]\n\n",
|
gfx_printf("[%kLo%kck%kpi%kck%k-R%kCM%k v%d.%d%k]\n\n",
|
||||||
colors[0], colors[1], colors[2], colors[3], colors[4], colors[5], 0xFFFF00FF, LP_VER_MJ, LP_VER_MN, 0xFFCCCCCC);
|
colors[0], colors[1], colors[2], colors[3], colors[4], colors[5], 0xFFFF00FF, LP_VER_MJ, LP_VER_MN, 0xFFCCCCCC);
|
||||||
|
|
||||||
u32 start_time = get_tmr_ms(),
|
u32 start_time = get_tmr_ms(),
|
||||||
|
@ -246,15 +246,6 @@ void dump_keys() {
|
||||||
u8 *pkg1 = (u8 *)malloc(0x40000);
|
u8 *pkg1 = (u8 *)malloc(0x40000);
|
||||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||||
/*FIL pk1fp;
|
|
||||||
FRESULT fres = FR_OK;
|
|
||||||
fres += f_open(&pk1fp, "sd:/test/package1", FA_READ | FA_OPEN_EXISTING);
|
|
||||||
fres += f_read(&pk1fp, pkg1, f_size(&pk1fp), NULL);
|
|
||||||
fres += f_close(&pk1fp);
|
|
||||||
if (fres != FR_OK) {
|
|
||||||
EPRINTF("failed to read pkg1 from sd");
|
|
||||||
goto out_wait;
|
|
||||||
}*/
|
|
||||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||||
if (!pkg1_id) {
|
if (!pkg1_id) {
|
||||||
EPRINTF("Unknown pkg1 version.");
|
EPRINTF("Unknown pkg1 version.");
|
||||||
|
@ -287,8 +278,8 @@ void dump_keys() {
|
||||||
u32 payload_size = *(u32 *)(IPL_LOAD_ADDR + 0x84) - IPL_LOAD_ADDR;
|
u32 payload_size = *(u32 *)(IPL_LOAD_ADDR + 0x84) - IPL_LOAD_ADDR;
|
||||||
f_write(&fp, (u8 *)IPL_LOAD_ADDR, payload_size, NULL);
|
f_write(&fp, (u8 *)IPL_LOAD_ADDR, payload_size, NULL);
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
gfx_printf(&gfx_con, "%kFirmware 7.x or higher detected.\n%kRenamed /sept/payload.bin", colors[0], colors[1]);
|
gfx_printf("%kFirmware 7.x or higher detected.\n%kRenamed /sept/payload.bin", colors[0], colors[1]);
|
||||||
gfx_printf(&gfx_con, "\n%k to /sept/payload.bak\n%kCopied self to /sept/payload.bin",colors[2], colors[3]);
|
gfx_printf("\n%k to /sept/payload.bak\n%kCopied self to /sept/payload.bin",colors[2], colors[3]);
|
||||||
sdmmc_storage_end(&storage);
|
sdmmc_storage_end(&storage);
|
||||||
if (!reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off))
|
if (!reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off))
|
||||||
goto out_wait;
|
goto out_wait;
|
||||||
|
@ -376,8 +367,8 @@ get_tsec: ;
|
||||||
se_aes_cmac(3, keyblob_mac, 0x10, keyblob_block + 0x10, 0xa0);
|
se_aes_cmac(3, keyblob_mac, 0x10, keyblob_block + 0x10, 0xa0);
|
||||||
if (memcmp(keyblob_block, keyblob_mac, 0x10)) {
|
if (memcmp(keyblob_block, keyblob_mac, 0x10)) {
|
||||||
EPRINTFARGS("Keyblob %x corrupt.", i);
|
EPRINTFARGS("Keyblob %x corrupt.", i);
|
||||||
gfx_hexdump(&gfx_con, i, keyblob_block, 0x10);
|
gfx_hexdump(i, keyblob_block, 0x10);
|
||||||
gfx_hexdump(&gfx_con, i, keyblob_mac, 0x10);
|
gfx_hexdump(i, keyblob_mac, 0x10);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,10 +424,6 @@ get_tsec: ;
|
||||||
|
|
||||||
// Read in package2 header and get package2 real size.
|
// Read in package2 header and get package2 real size.
|
||||||
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||||
/*FIL pkg2fp;
|
|
||||||
fres = FR_OK;
|
|
||||||
fres += f_open(&pkg2fp, "sd:/test/package2", FA_READ | FA_OPEN_EXISTING);
|
|
||||||
fres += f_read(&pkg2fp, tmp, NX_EMMC_BLOCKSIZE, NULL);*/
|
|
||||||
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
|
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
|
||||||
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
|
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
|
||||||
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
|
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
|
||||||
|
@ -449,13 +436,6 @@ get_tsec: ;
|
||||||
// Read in package2.
|
// Read in package2.
|
||||||
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
|
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
|
||||||
pkg2 = malloc(pkg2_size_aligned);
|
pkg2 = malloc(pkg2_size_aligned);
|
||||||
/*fres += f_lseek(&pkg2fp, 0);
|
|
||||||
fres += f_read(&pkg2fp, pkg2, f_size(&pkg2fp), NULL);
|
|
||||||
fres += f_close(&pkg2fp);
|
|
||||||
if (fres != FR_OK) {
|
|
||||||
EPRINTF("failed to read pkg2 from sd");
|
|
||||||
goto pkg2_done;
|
|
||||||
}*/
|
|
||||||
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
|
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
|
||||||
|
|
||||||
// Decrypt package2 and parse KIP1 blobs in INI1 section.
|
// Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||||
|
@ -881,19 +861,19 @@ key_output: ;
|
||||||
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
||||||
SAVE_KEY("tsec_root_key", tsec_keys + 0x10, 0x10);
|
SAVE_KEY("tsec_root_key", tsec_keys + 0x10, 0x10);
|
||||||
|
|
||||||
//gfx_con.fntsz = 8; gfx_puts(&gfx_con, text_buffer); gfx_con.fntsz = 16;
|
//gfx_con.fntsz = 8; gfx_puts(text_buffer); gfx_con.fntsz = 16;
|
||||||
|
|
||||||
TPRINTFARGS("\n%kFound %d keys.\n%kLockpick totally", colors[0], _key_count, colors[1]);
|
TPRINTFARGS("\n%kFound %d keys.\n%kLockpick totally", colors[0], _key_count, colors[1]);
|
||||||
|
|
||||||
f_mkdir("switch");
|
f_mkdir("switch");
|
||||||
if (!sd_save_to_file(text_buffer, buf_index, "sd:/switch/prod.keys"))
|
if (!sd_save_to_file(text_buffer, buf_index, "sd:/switch/prod.keys"))
|
||||||
gfx_printf(&gfx_con, "%kWrote %d bytes to /switch/prod.keys\n", colors[2], buf_index);
|
gfx_printf("%kWrote %d bytes to /switch/prod.keys\n", colors[2], buf_index);
|
||||||
else
|
else
|
||||||
EPRINTF("Failed to save keys to SD.");
|
EPRINTF("Failed to save keys to SD.");
|
||||||
sd_unmount();
|
sd_unmount();
|
||||||
free(text_buffer);
|
free(text_buffer);
|
||||||
|
|
||||||
gfx_printf(&gfx_con, "\n%kVOL + -> Reboot to RCM\n%kVOL - -> Reboot normally\n%kPower -> Power off", colors[3], colors[4], colors[5]);
|
gfx_printf("\n%kVOL + -> Reboot to RCM\n%kVOL - -> Reboot normally\n%kPower -> Power off", colors[3], colors[4], colors[5]);
|
||||||
|
|
||||||
out_wait: ;
|
out_wait: ;
|
||||||
u32 btn = btn_wait();
|
u32 btn = btn_wait();
|
||||||
|
|
|
@ -166,7 +166,7 @@ DRESULT disk_read (
|
||||||
memcpy(tweak, sector_cache[s].tweak, 0x10);
|
memcpy(tweak, sector_cache[s].tweak, 0x10);
|
||||||
prev_sector = sector;
|
prev_sector = sector;
|
||||||
prev_cluster = sector / 0x20;
|
prev_cluster = sector / 0x20;
|
||||||
//gfx_printf(&gfx_con, "addr %x sec %x count %x cached\n", sector * 0x200, sector, count);
|
//gfx_printf("addr %x sec %x count %x cached\n", sector * 0x200, sector, count);
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ DRESULT disk_read (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nx_emmc_part_read(&storage, system_part, sector, count, buff)) {
|
if (nx_emmc_part_read(&storage, system_part, sector, count, buff)) {
|
||||||
//gfx_hexdump(&gfx_con, 0, buff, 0x100);
|
//gfx_hexdump(0, buff, 0x100);
|
||||||
if (prev_cluster != sector / 0x20) { // sector in different cluster than last read
|
if (prev_cluster != sector / 0x20) { // sector in different cluster than last read
|
||||||
prev_cluster = sector / 0x20;
|
prev_cluster = sector / 0x20;
|
||||||
tweak_exp = sector % 0x20;
|
tweak_exp = sector % 0x20;
|
||||||
|
@ -192,13 +192,13 @@ DRESULT disk_read (
|
||||||
}
|
}
|
||||||
|
|
||||||
// fatfs will never pull more than a cluster
|
// fatfs will never pull more than a cluster
|
||||||
//gfx_printf(&gfx_con, "sec %6x count %2x tweak %2x\n", sector, count, tweak_exp);
|
//gfx_printf("sec %6x count %2x tweak %2x\n", sector, count, tweak_exp);
|
||||||
_emmc_xts(9, 8, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200);
|
_emmc_xts(9, 8, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count * 0x200);
|
||||||
if (cache_sector) {
|
if (cache_sector) {
|
||||||
memcpy(sector_cache[s].cached_sector, buff, 0x200);
|
memcpy(sector_cache[s].cached_sector, buff, 0x200);
|
||||||
memcpy(sector_cache[s].tweak, tweak, 0x10);
|
memcpy(sector_cache[s].tweak, tweak, 0x10);
|
||||||
}
|
}
|
||||||
//gfx_hexdump(&gfx_con, 0, buff, 0x10);
|
//gfx_hexdump(0, buff, 0x10);
|
||||||
prev_sector = sector + count - 1;
|
prev_sector = sector + count - 1;
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ extern "C" {
|
||||||
|
|
||||||
#include "../../utils/types.h"
|
#include "../../utils/types.h"
|
||||||
|
|
||||||
|
|
||||||
/* Status of Disk Functions */
|
/* Status of Disk Functions */
|
||||||
typedef BYTE DSTATUS;
|
typedef BYTE DSTATUS;
|
||||||
|
|
||||||
|
@ -46,11 +45,11 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||||
/* Command code for disk_ioctrl fucntion */
|
/* Command code for disk_ioctrl fucntion */
|
||||||
|
|
||||||
/* Generic command (Used by FatFs) */
|
/* Generic command (Used by FatFs) */
|
||||||
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
|
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
|
||||||
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
|
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
|
||||||
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
|
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
|
||||||
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
|
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
|
||||||
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
|
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
|
||||||
|
|
||||||
/* Generic command (Not used by FatFs) */
|
/* Generic command (Not used by FatFs) */
|
||||||
#define CTRL_POWER 5 /* Get/Set power status */
|
#define CTRL_POWER 5 /* Get/Set power status */
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - Generic FAT Filesystem Module R0.13b /
|
/ FatFs - Generic FAT Filesystem Module R0.13c (p3) /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2018, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
/ Copyright (c) 2018 naehrwert
|
/ Copyright (c) 2018 naehrwert
|
||||||
/ Copyright (C) 2018 CTCaer
|
/ Copyright (C) 2018-2019 CTCaer
|
||||||
/
|
/
|
||||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||||
/ source and binary forms, with or without modification, are permitted provided
|
/ source and binary forms, with or without modification, are permitted provided
|
||||||
|
@ -23,9 +23,9 @@
|
||||||
|
|
||||||
#include "ff.h" /* Declarations of FatFs API */
|
#include "ff.h" /* Declarations of FatFs API */
|
||||||
#include "diskio.h" /* Declarations of device I/O functions */
|
#include "diskio.h" /* Declarations of device I/O functions */
|
||||||
|
|
||||||
#include "../../gfx/gfx.h"
|
#include "../../gfx/gfx.h"
|
||||||
#define EFSPRINTF(text, ...) print_error(); gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
|
|
||||||
|
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
|
||||||
//#define EFSPRINTF(...)
|
//#define EFSPRINTF(...)
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
/*--------------------------------------------------------------------------
|
||||||
|
@ -34,11 +34,20 @@
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#if FF_DEFINED != 63463 /* Revision ID */
|
#if FF_DEFINED != 86604 /* Revision ID */
|
||||||
#error Wrong include file (ff.h).
|
#error Wrong include file (ff.h).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Limits and boundaries */
|
||||||
|
#define MAX_DIR 0x200000 /* Max size of FAT directory */
|
||||||
|
#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */
|
||||||
|
#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
||||||
|
#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
||||||
|
#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */
|
||||||
|
#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */
|
||||||
|
|
||||||
|
|
||||||
/* Character code support macros */
|
/* Character code support macros */
|
||||||
#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
|
#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
|
||||||
#define IsLower(c) ((c) >= 'a' && (c) <= 'z')
|
#define IsLower(c) ((c) >= 'a' && (c) <= 'z')
|
||||||
|
@ -48,18 +57,18 @@
|
||||||
#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF)
|
#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF)
|
||||||
|
|
||||||
|
|
||||||
/* Additional file attribute bits for internal use */
|
|
||||||
#define AM_VOL 0x08 /* Volume label */
|
|
||||||
#define AM_LFN 0x0F /* LFN entry */
|
|
||||||
#define AM_MASK 0x3F /* Mask of defined bits */
|
|
||||||
|
|
||||||
|
|
||||||
/* Additional file access control and file status flags for internal use */
|
/* Additional file access control and file status flags for internal use */
|
||||||
#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */
|
#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */
|
||||||
#define FA_MODIFIED 0x40 /* File has been modified */
|
#define FA_MODIFIED 0x40 /* File has been modified */
|
||||||
#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */
|
#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */
|
||||||
|
|
||||||
|
|
||||||
|
/* Additional file attribute bits for internal use */
|
||||||
|
#define AM_VOL 0x08 /* Volume label */
|
||||||
|
#define AM_LFN 0x0F /* LFN entry */
|
||||||
|
#define AM_MASK 0x3F /* Mask of defined bits */
|
||||||
|
|
||||||
|
|
||||||
/* Name status flags in fn[11] */
|
/* Name status flags in fn[11] */
|
||||||
#define NSFLAG 11 /* Index of the name status byte */
|
#define NSFLAG 11 /* Index of the name status byte */
|
||||||
#define NS_LOSS 0x01 /* Out of 8.3 format */
|
#define NS_LOSS 0x01 /* Out of 8.3 format */
|
||||||
|
@ -72,13 +81,13 @@
|
||||||
#define NS_NONAME 0x80 /* Not followed */
|
#define NS_NONAME 0x80 /* Not followed */
|
||||||
|
|
||||||
|
|
||||||
/* Limits and boundaries */
|
/* exFAT directory entry types */
|
||||||
#define MAX_DIR 0x200000 /* Max size of FAT directory */
|
#define ET_BITMAP 0x81 /* Allocation bitmap */
|
||||||
#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */
|
#define ET_UPCASE 0x82 /* Up-case table */
|
||||||
#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
#define ET_VLABEL 0x83 /* Volume label */
|
||||||
#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
#define ET_FILEDIR 0x85 /* File and directory */
|
||||||
#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */
|
#define ET_STREAM 0xC0 /* Stream extension */
|
||||||
#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */
|
#define ET_FILENAME 0xC1 /* Name extension */
|
||||||
|
|
||||||
|
|
||||||
/* FatFs refers the FAT structure as simple byte array instead of structure member
|
/* FatFs refers the FAT structure as simple byte array instead of structure member
|
||||||
|
@ -526,6 +535,7 @@ static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */
|
||||||
#define CODEPAGE CodePage
|
#define CODEPAGE CodePage
|
||||||
static WORD CodePage; /* Current code page */
|
static WORD CodePage; /* Current code page */
|
||||||
static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */
|
static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */
|
||||||
|
|
||||||
static const BYTE Ct437[] = TBL_CT437;
|
static const BYTE Ct437[] = TBL_CT437;
|
||||||
static const BYTE Ct720[] = TBL_CT720;
|
static const BYTE Ct720[] = TBL_CT720;
|
||||||
static const BYTE Ct737[] = TBL_CT737;
|
static const BYTE Ct737[] = TBL_CT737;
|
||||||
|
@ -573,7 +583,7 @@ static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE);
|
||||||
|
|
||||||
void print_error()
|
void print_error()
|
||||||
{
|
{
|
||||||
gfx_printf(&gfx_con, "\n\n\n%k[FatFS] Error: %k", 0xFFFFFF00, 0xFFFFFFFF);
|
gfx_printf("\n\n\n%k[FatFS] Error: %k", 0xFFFFFF00, 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1107,7 +1117,7 @@ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */
|
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */
|
||||||
/* Create FSInfo structure */
|
/* Create FSInfo structure */
|
||||||
mem_set(fs->win, 0, SS(fs));
|
mem_set(fs->win, 0, sizeof fs->win);
|
||||||
st_word(fs->win + BS_55AA, 0xAA55);
|
st_word(fs->win + BS_55AA, 0xAA55);
|
||||||
st_dword(fs->win + FSI_LeadSig, 0x41615252);
|
st_dword(fs->win + FSI_LeadSig, 0x41615252);
|
||||||
st_dword(fs->win + FSI_StrucSig, 0x61417272);
|
st_dword(fs->win + FSI_StrucSig, 0x61417272);
|
||||||
|
@ -1307,7 +1317,7 @@ static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:D
|
||||||
if (clst >= fs->n_fatent - 2) clst = 0;
|
if (clst >= fs->n_fatent - 2) clst = 0;
|
||||||
scl = val = clst; ctr = 0;
|
scl = val = clst; ctr = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; /* (assuming bitmap is located top of the cluster heap) */
|
if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF;
|
||||||
i = val / 8 % SS(fs); bm = 1 << (val % 8);
|
i = val / 8 % SS(fs); bm = 1 << (val % 8);
|
||||||
do {
|
do {
|
||||||
do {
|
do {
|
||||||
|
@ -1345,7 +1355,7 @@ static FRESULT change_bitmap (
|
||||||
|
|
||||||
|
|
||||||
clst -= 2; /* The first bit corresponds to cluster #2 */
|
clst -= 2; /* The first bit corresponds to cluster #2 */
|
||||||
sect = fs->database + clst / 8 / SS(fs); /* Sector address (assuming bitmap is located top of the cluster heap) */
|
sect = fs->bitbase + clst / 8 / SS(fs); /* Sector address */
|
||||||
i = clst / 8 % SS(fs); /* Byte offset in the sector */
|
i = clst / 8 % SS(fs); /* Byte offset in the sector */
|
||||||
bm = 1 << (clst % 8); /* Bit mask in the byte */
|
bm = 1 << (clst % 8); /* Bit mask in the byte */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -1420,7 +1430,7 @@ static FRESULT fill_last_frag (
|
||||||
static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */
|
static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
FFOBJID* obj, /* Corresponding object */
|
FFOBJID* obj, /* Corresponding object */
|
||||||
DWORD clst, /* Cluster to remove a chain from */
|
DWORD clst, /* Cluster to remove a chain from */
|
||||||
DWORD pclst /* Previous cluster of clst (0:entire chain) */
|
DWORD pclst /* Previous cluster of clst (0 if entire chain) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
FRESULT res = FR_OK;
|
FRESULT res = FR_OK;
|
||||||
|
@ -1658,7 +1668,7 @@ static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */
|
||||||
if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */
|
if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */
|
||||||
sect = clst2sect(fs, clst); /* Top of the cluster */
|
sect = clst2sect(fs, clst); /* Top of the cluster */
|
||||||
fs->winsect = sect; /* Set window to top of the cluster */
|
fs->winsect = sect; /* Set window to top of the cluster */
|
||||||
mem_set(fs->win, 0, SS(fs)); /* Clear window buffer */
|
mem_set(fs->win, 0, sizeof fs->win); /* Clear window buffer */
|
||||||
#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */
|
#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */
|
||||||
/* Allocate a temporary buffer */
|
/* Allocate a temporary buffer */
|
||||||
for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ;
|
for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ;
|
||||||
|
@ -1888,7 +1898,7 @@ static int cmp_lfn ( /* 1:matched, 0:not matched */
|
||||||
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
||||||
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
||||||
if (wc != 0) {
|
if (wc != 0) {
|
||||||
if (i >= FF_MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */
|
if (i >= FF_MAX_LFN + 1 || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */
|
||||||
return 0; /* Not matched */
|
return 0; /* Not matched */
|
||||||
}
|
}
|
||||||
wc = uc;
|
wc = uc;
|
||||||
|
@ -1924,15 +1934,15 @@ static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */
|
||||||
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
||||||
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
||||||
if (wc != 0) {
|
if (wc != 0) {
|
||||||
if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */
|
if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */
|
||||||
lfnbuf[i++] = wc = uc; /* Store it */
|
lfnbuf[i++] = wc = uc; /* Store it */
|
||||||
} else {
|
} else {
|
||||||
if (uc != 0xFFFF) return 0; /* Check filler */
|
if (uc != 0xFFFF) return 0; /* Check filler */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */
|
if (dir[LDIR_Ord] & LLEF && wc != 0) { /* Put terminator if it is the last LFN part and not terminated */
|
||||||
if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */
|
if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */
|
||||||
lfnbuf[i] = 0;
|
lfnbuf[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2168,33 +2178,33 @@ static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */
|
||||||
BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */
|
BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */
|
||||||
|
|
||||||
|
|
||||||
/* Load 85 entry */
|
/* Load file-directory entry */
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0x85) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR; /* Invalid order */
|
||||||
mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
|
mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
|
||||||
sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
|
sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
|
||||||
if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
|
if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
|
||||||
|
|
||||||
/* Load C0 entry */
|
/* Load stream-extension entry */
|
||||||
res = dir_next(dp, 0);
|
res = dir_next(dp, 0);
|
||||||
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0xC0) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR; /* Invalid order */
|
||||||
mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
|
mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
|
||||||
if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
|
if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
|
||||||
|
|
||||||
/* Load C1 entries */
|
/* Load file-name entries */
|
||||||
i = 2 * SZDIRE; /* C1 offset to load */
|
i = 2 * SZDIRE; /* Name offset to load */
|
||||||
do {
|
do {
|
||||||
res = dir_next(dp, 0);
|
res = dir_next(dp, 0);
|
||||||
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0xC1) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_FILENAME) return FR_INT_ERR; /* Invalid order */
|
||||||
if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
|
if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
|
||||||
} while ((i += SZDIRE) < sz_ent);
|
} while ((i += SZDIRE) < sz_ent);
|
||||||
|
|
||||||
|
@ -2299,16 +2309,16 @@ static void create_xdir (
|
||||||
WCHAR wc;
|
WCHAR wc;
|
||||||
|
|
||||||
|
|
||||||
/* Create 85,C0 entry */
|
/* Create file-directory and stream-extension entry */
|
||||||
mem_set(dirb, 0, 2 * SZDIRE);
|
mem_set(dirb, 0, 2 * SZDIRE);
|
||||||
dirb[0 * SZDIRE + XDIR_Type] = 0x85; /* 85 entry */
|
dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR;
|
||||||
dirb[1 * SZDIRE + XDIR_Type] = 0xC0; /* C0 entry */
|
dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM;
|
||||||
|
|
||||||
/* Create C1 entries */
|
/* Create file-name entries */
|
||||||
i = SZDIRE * 2; /* Top of C1 entries */
|
i = SZDIRE * 2; /* Top of file_name entries */
|
||||||
nlen = nc1 = 0; wc = 1;
|
nlen = nc1 = 0; wc = 1;
|
||||||
do {
|
do {
|
||||||
dirb[i++] = 0xC1; dirb[i++] = 0; /* Entry type C1 */
|
dirb[i++] = ET_FILENAME; dirb[i++] = 0;
|
||||||
do { /* Fill name field */
|
do { /* Fill name field */
|
||||||
if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */
|
if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */
|
||||||
st_word(dirb + i, wc); /* Store it */
|
st_word(dirb + i, wc); /* Store it */
|
||||||
|
@ -2332,8 +2342,8 @@ static void create_xdir (
|
||||||
/* Read an object from the directory */
|
/* Read an object from the directory */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define dir_read_file(dp) dir_read(dp, 0)
|
#define DIR_READ_FILE(dp) dir_read(dp, 0)
|
||||||
#define dir_read_label(dp) dir_read(dp, 1)
|
#define DIR_READ_LABEL(dp) dir_read(dp, 1)
|
||||||
|
|
||||||
static FRESULT dir_read (
|
static FRESULT dir_read (
|
||||||
DIR* dp, /* Pointer to the directory object */
|
DIR* dp, /* Pointer to the directory object */
|
||||||
|
@ -2342,7 +2352,7 @@ static FRESULT dir_read (
|
||||||
{
|
{
|
||||||
FRESULT res = FR_NO_FILE;
|
FRESULT res = FR_NO_FILE;
|
||||||
FATFS *fs = dp->obj.fs;
|
FATFS *fs = dp->obj.fs;
|
||||||
BYTE a, c;
|
BYTE attr, b;
|
||||||
#if FF_USE_LFN
|
#if FF_USE_LFN
|
||||||
BYTE ord = 0xFF, sum = 0xFF;
|
BYTE ord = 0xFF, sum = 0xFF;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2350,16 +2360,16 @@ static FRESULT dir_read (
|
||||||
while (dp->sect) {
|
while (dp->sect) {
|
||||||
res = move_window(fs, dp->sect);
|
res = move_window(fs, dp->sect);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
c = dp->dir[DIR_Name]; /* Test for the entry type */
|
b = dp->dir[DIR_Name]; /* Test for the entry type */
|
||||||
if (c == 0) {
|
if (b == 0) {
|
||||||
res = FR_NO_FILE; break; /* Reached to end of the directory */
|
res = FR_NO_FILE; break; /* Reached to end of the directory */
|
||||||
}
|
}
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
||||||
if (FF_USE_LABEL && vol) {
|
if (FF_USE_LABEL && vol) {
|
||||||
if (c == 0x83) break; /* Volume label entry? */
|
if (b == ET_VLABEL) break; /* Volume label entry? */
|
||||||
} else {
|
} else {
|
||||||
if (c == 0x85) { /* Start of the file entry block? */
|
if (b == ET_FILEDIR) { /* Start of the file entry block? */
|
||||||
dp->blk_ofs = dp->dptr; /* Get location of the block */
|
dp->blk_ofs = dp->dptr; /* Get location of the block */
|
||||||
res = load_xdir(dp); /* Load the entry block */
|
res = load_xdir(dp); /* Load the entry block */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
|
@ -2371,19 +2381,19 @@ static FRESULT dir_read (
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{ /* On the FAT/FAT32 volume */
|
{ /* On the FAT/FAT32 volume */
|
||||||
dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */
|
dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */
|
||||||
#if FF_USE_LFN /* LFN configuration */
|
#if FF_USE_LFN /* LFN configuration */
|
||||||
if (c == DDEM || c == '.' || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
|
if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
|
||||||
ord = 0xFF;
|
ord = 0xFF;
|
||||||
} else {
|
} else {
|
||||||
if (a == AM_LFN) { /* An LFN entry is found */
|
if (attr == AM_LFN) { /* An LFN entry is found */
|
||||||
if (c & LLEF) { /* Is it start of an LFN sequence? */
|
if (b & LLEF) { /* Is it start of an LFN sequence? */
|
||||||
sum = dp->dir[LDIR_Chksum];
|
sum = dp->dir[LDIR_Chksum];
|
||||||
c &= (BYTE)~LLEF; ord = c;
|
b &= (BYTE)~LLEF; ord = b;
|
||||||
dp->blk_ofs = dp->dptr;
|
dp->blk_ofs = dp->dptr;
|
||||||
}
|
}
|
||||||
/* Check LFN validity and capture it */
|
/* Check LFN validity and capture it */
|
||||||
ord = (c == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
|
ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
|
||||||
} else { /* An SFN entry is found */
|
} else { /* An SFN entry is found */
|
||||||
if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */
|
if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */
|
||||||
dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */
|
dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */
|
||||||
|
@ -2392,7 +2402,7 @@ static FRESULT dir_read (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* Non LFN configuration */
|
#else /* Non LFN configuration */
|
||||||
if (c != DDEM && c != '.' && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */
|
if (b != DDEM && b != '.' && attr != AM_LFN && (int)((attr & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2432,7 +2442,7 @@ static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
UINT di, ni;
|
UINT di, ni;
|
||||||
WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */
|
WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */
|
||||||
|
|
||||||
while ((res = dir_read_file(dp)) == FR_OK) { /* Read an item */
|
while ((res = DIR_READ_FILE(dp)) == FR_OK) { /* Read an item */
|
||||||
#if FF_MAX_LFN < 255
|
#if FF_MAX_LFN < 255
|
||||||
if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */
|
if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */
|
||||||
#endif
|
#endif
|
||||||
|
@ -2511,17 +2521,17 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
||||||
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
|
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
|
||||||
res = dir_alloc(dp, nent); /* Allocate entries */
|
res = dir_alloc(dp, nent); /* Allocate directory entries */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */
|
dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */
|
||||||
|
|
||||||
if (dp->obj.stat & 4) { /* Has the directory been stretched? */
|
if (dp->obj.stat & 4) { /* Has the directory been stretched by new allocation? */
|
||||||
dp->obj.stat &= ~4;
|
dp->obj.stat &= ~4;
|
||||||
res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
|
res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */
|
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->obj.sclust != 0) { /* Is it a sub directory? */
|
if (dp->obj.sclust != 0) { /* Is it a sub-directory? */
|
||||||
DIR dj;
|
DIR dj;
|
||||||
|
|
||||||
res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */
|
res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */
|
||||||
|
@ -2653,6 +2663,7 @@ static void get_fileinfo (
|
||||||
{
|
{
|
||||||
UINT si, di;
|
UINT si, di;
|
||||||
#if FF_USE_LFN
|
#if FF_USE_LFN
|
||||||
|
BYTE lcf;
|
||||||
WCHAR wc, hs;
|
WCHAR wc, hs;
|
||||||
FATFS *fs = dp->obj.fs;
|
FATFS *fs = dp->obj.fs;
|
||||||
#else
|
#else
|
||||||
|
@ -2713,9 +2724,10 @@ static void get_fileinfo (
|
||||||
if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */
|
if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */
|
||||||
fno->fname[di++] = '?';
|
fno->fname[di++] = '?';
|
||||||
} else {
|
} else {
|
||||||
for (si = di = 0; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */
|
for (si = di = 0, lcf = NS_BODY; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */
|
||||||
wc = (WCHAR)fno->altname[si];
|
wc = (WCHAR)fno->altname[si];
|
||||||
if (IsUpper(wc) && (dp->dir[DIR_NTres] & ((si >= 9) ? NS_EXT : NS_BODY))) wc += 0x20;
|
if (wc == '.') lcf = NS_EXT;
|
||||||
|
if (IsUpper(wc) && (dp->dir[DIR_NTres] & lcf)) wc += 0x20;
|
||||||
fno->fname[di] = (TCHAR)wc;
|
fno->fname[di] = (TCHAR)wc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3272,7 +3284,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
|
if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK and SFD. */
|
/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK (MBR) and SFD (w/o partition). */
|
||||||
bsect = 0;
|
bsect = 0;
|
||||||
fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */
|
fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */
|
||||||
if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */
|
if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */
|
||||||
|
@ -3301,13 +3313,12 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fmt == 1) {
|
if (fmt == 1) {
|
||||||
QWORD maxlba;
|
QWORD maxlba;
|
||||||
|
DWORD so, cv, bcl;
|
||||||
|
|
||||||
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
|
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
|
||||||
if (i < BPB_ZeroedEx + 53)
|
if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
|
||||||
return FR_NO_FILESYSTEM;
|
|
||||||
|
|
||||||
if (ld_word(fs->win + BPB_FSVerEx) != 0x100)
|
if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */
|
||||||
return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */
|
|
||||||
|
|
||||||
if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */
|
if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */
|
||||||
EFSPRINTF("EXSPS");
|
EFSPRINTF("EXSPS");
|
||||||
|
@ -3315,8 +3326,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
}
|
}
|
||||||
|
|
||||||
maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */
|
maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */
|
||||||
if (maxlba >= 0x100000000)
|
if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */
|
||||||
return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */
|
|
||||||
|
|
||||||
fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */
|
fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */
|
||||||
|
|
||||||
|
@ -3327,35 +3337,49 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
}
|
}
|
||||||
|
|
||||||
fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */
|
fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */
|
||||||
if (fs->csize == 0) {
|
if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must be 1..32768) */
|
|
||||||
}
|
|
||||||
|
|
||||||
nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */
|
nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */
|
||||||
if (nclst > MAX_EXFAT)
|
if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */
|
||||||
return FR_NO_FILESYSTEM; /* (Too many clusters) */
|
|
||||||
fs->n_fatent = nclst + 2;
|
fs->n_fatent = nclst + 2;
|
||||||
|
|
||||||
/* Boundaries and Limits */
|
/* Boundaries and Limits */
|
||||||
fs->volbase = bsect;
|
fs->volbase = bsect;
|
||||||
fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
|
fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
|
||||||
fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
|
fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
|
||||||
if (maxlba < (QWORD)fs->database + nclst * fs->csize)
|
if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */
|
||||||
return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size required) */
|
|
||||||
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
|
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
|
||||||
|
|
||||||
/* Check if bitmap location is in assumption (at the first cluster) */
|
/* Get bitmap location and check if it is contiguous (implementation assumption) */
|
||||||
if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) {
|
so = i = 0;
|
||||||
|
for (;;) { /* Find the bitmap entry in the root directory (in only first cluster) */
|
||||||
|
if (i == 0) {
|
||||||
|
if (so >= fs->csize) return FR_NO_FILESYSTEM; /* Not found? */
|
||||||
|
if (move_window(fs, clst2sect(fs, fs->dirbase) + so) != FR_OK) {
|
||||||
EFSPRINTF("EXBM1C");
|
EFSPRINTF("EXBM1C");
|
||||||
return FR_DISK_ERR;
|
return FR_DISK_ERR;
|
||||||
}
|
}
|
||||||
for (i = 0; i < SS(fs); i += SZDIRE) {
|
so++;
|
||||||
if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */
|
|
||||||
}
|
}
|
||||||
if (i == SS(fs)) {
|
if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */
|
||||||
|
i = (i + SZDIRE) % SS(fs); /* Next entry */
|
||||||
|
}
|
||||||
|
bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */
|
||||||
|
if (bcl < 2 || bcl >= fs->n_fatent) {
|
||||||
EFSPRINTF("EXBMM");
|
EFSPRINTF("EXBMM");
|
||||||
return FR_NO_FILESYSTEM;
|
return FR_NO_FILESYSTEM;
|
||||||
}
|
}
|
||||||
|
fs->bitbase = fs->database + fs->csize * (bcl - 2); /* Bitmap sector */
|
||||||
|
for (;;) { /* Check if bitmap is contiguous */
|
||||||
|
if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR;
|
||||||
|
cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4);
|
||||||
|
if (cv == 0xFFFFFFFF) break; /* Last link? */
|
||||||
|
if (cv != ++bcl) {
|
||||||
|
EFSPRINTF("EXBMM");
|
||||||
|
return FR_NO_FILESYSTEM; /* Fragmented? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */
|
fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */
|
||||||
#endif
|
#endif
|
||||||
|
@ -3373,38 +3397,31 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
fs->fsize = fasize;
|
fs->fsize = fasize;
|
||||||
|
|
||||||
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */
|
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */
|
||||||
if (fs->n_fats != 1 && fs->n_fats != 2)
|
if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
|
|
||||||
fasize *= fs->n_fats; /* Number of sectors for FAT area */
|
fasize *= fs->n_fats; /* Number of sectors for FAT area */
|
||||||
|
|
||||||
fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */
|
fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */
|
||||||
if (fs->csize == 0 || (fs->csize & (fs->csize - 1)))
|
if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must be power of 2) */
|
|
||||||
|
|
||||||
fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */
|
fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */
|
||||||
if (fs->n_rootdir % (SS(fs) / SZDIRE))
|
if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must be sector aligned) */
|
|
||||||
|
|
||||||
tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */
|
tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */
|
||||||
if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
|
if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
|
||||||
|
|
||||||
nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */
|
nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */
|
||||||
if (nrsv == 0)
|
if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must not be 0) */
|
|
||||||
|
|
||||||
/* Determine the FAT sub type */
|
/* Determine the FAT sub type */
|
||||||
sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */
|
sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */
|
||||||
if (tsect < sysect)
|
if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
||||||
return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
|
||||||
nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
|
nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
|
||||||
if (nclst == 0)
|
if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
||||||
return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
|
||||||
fmt = 0;
|
fmt = 0;
|
||||||
if (nclst <= MAX_FAT32) fmt = FS_FAT32;
|
if (nclst <= MAX_FAT32) fmt = FS_FAT32;
|
||||||
if (nclst <= MAX_FAT16) fmt = FS_FAT16;
|
if (nclst <= MAX_FAT16) fmt = FS_FAT16;
|
||||||
if (nclst <= MAX_FAT12) fmt = FS_FAT12;
|
if (nclst <= MAX_FAT12) fmt = FS_FAT12;
|
||||||
if (fmt == 0)
|
if (fmt == 0) return FR_NO_FILESYSTEM;
|
||||||
return FR_NO_FILESYSTEM;
|
|
||||||
|
|
||||||
/* Boundaries and Limits */
|
/* Boundaries and Limits */
|
||||||
fs->n_fatent = nclst + 2; /* Number of FAT entries */
|
fs->n_fatent = nclst + 2; /* Number of FAT entries */
|
||||||
|
@ -3412,21 +3429,17 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
fs->fatbase = bsect + nrsv; /* FAT start sector */
|
fs->fatbase = bsect + nrsv; /* FAT start sector */
|
||||||
fs->database = bsect + sysect; /* Data start sector */
|
fs->database = bsect + sysect; /* Data start sector */
|
||||||
if (fmt == FS_FAT32) {
|
if (fmt == FS_FAT32) {
|
||||||
if (ld_word(fs->win + BPB_FSVer32) != 0)
|
if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */
|
if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
|
||||||
if (fs->n_rootdir != 0)
|
|
||||||
return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
|
|
||||||
fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */
|
fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */
|
||||||
szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
|
szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
|
||||||
} else {
|
} else {
|
||||||
if (fs->n_rootdir == 0)
|
if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
|
||||||
return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
|
|
||||||
fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
|
fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
|
||||||
szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */
|
szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */
|
||||||
fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
|
fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
|
||||||
}
|
}
|
||||||
if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs))
|
if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */
|
||||||
return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */
|
|
||||||
|
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
/* Get FSInfo if available */
|
/* Get FSInfo if available */
|
||||||
|
@ -3459,7 +3472,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
#if FF_USE_LFN == 1
|
#if FF_USE_LFN == 1
|
||||||
fs->lfnbuf = LfnBuf; /* Static LFN working buffer */
|
fs->lfnbuf = LfnBuf; /* Static LFN working buffer */
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
fs->dirbuf = DirBuf; /* Static directory block scratchpad buffer */
|
fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if FF_FS_RPATH != 0
|
#if FF_FS_RPATH != 0
|
||||||
|
@ -3722,7 +3735,7 @@ FRESULT f_open (
|
||||||
fp->fptr = 0; /* Set file pointer top of the file */
|
fp->fptr = 0; /* Set file pointer top of the file */
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
#if !FF_FS_TINY
|
#if !FF_FS_TINY
|
||||||
mem_set(fp->buf, 0, FF_MAX_SS); /* Clear sector buffer */
|
mem_set(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */
|
||||||
#endif
|
#endif
|
||||||
if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */
|
if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */
|
||||||
fp->fptr = fp->obj.objsize; /* Offset to seek */
|
fp->fptr = fp->obj.objsize; /* Offset to seek */
|
||||||
|
@ -3777,7 +3790,6 @@ FRESULT f_read (
|
||||||
UINT rcnt, cc, csect;
|
UINT rcnt, cc, csect;
|
||||||
BYTE *rbuff = (BYTE*)buff;
|
BYTE *rbuff = (BYTE*)buff;
|
||||||
|
|
||||||
|
|
||||||
UINT br_tmp;
|
UINT br_tmp;
|
||||||
if (!br)
|
if (!br)
|
||||||
br = &br_tmp;
|
br = &br_tmp;
|
||||||
|
@ -3787,10 +3799,7 @@ FRESULT f_read (
|
||||||
EFSPRINTF("FOV");
|
EFSPRINTF("FOV");
|
||||||
LEAVE_FF(fs, res); /* Check validity */
|
LEAVE_FF(fs, res); /* Check validity */
|
||||||
}
|
}
|
||||||
if (!(fp->flag & FA_READ)) {
|
if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
|
||||||
EFSPRINTF("NOACCESS");
|
|
||||||
LEAVE_FF(fs, FR_DENIED); /* Check access mode */
|
|
||||||
}
|
|
||||||
remain = fp->obj.objsize - fp->fptr;
|
remain = fp->obj.objsize - fp->fptr;
|
||||||
if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
|
if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
|
||||||
|
|
||||||
|
@ -3822,9 +3831,7 @@ FRESULT f_read (
|
||||||
fp->clust = clst; /* Update current cluster */
|
fp->clust = clst; /* Update current cluster */
|
||||||
}
|
}
|
||||||
sect = clst2sect(fs, fp->clust); /* Get current sector */
|
sect = clst2sect(fs, fp->clust); /* Get current sector */
|
||||||
if (sect == 0) {
|
if (sect == 0) ABORT(fs, FR_INT_ERR);
|
||||||
ABORT(fs, FR_INT_ERR);
|
|
||||||
}
|
|
||||||
sect += csect;
|
sect += csect;
|
||||||
cc = btr / SS(fs); /* When remaining bytes >= sector size, */
|
cc = btr / SS(fs); /* When remaining bytes >= sector size, */
|
||||||
if (cc > 0) { /* Read maximum contiguous sectors directly */
|
if (cc > 0) { /* Read maximum contiguous sectors directly */
|
||||||
|
@ -3902,7 +3909,6 @@ FRESULT f_write (
|
||||||
UINT wcnt, cc, csect;
|
UINT wcnt, cc, csect;
|
||||||
const BYTE *wbuff = (const BYTE*)buff;
|
const BYTE *wbuff = (const BYTE*)buff;
|
||||||
|
|
||||||
|
|
||||||
UINT bw_tmp;
|
UINT bw_tmp;
|
||||||
if (!bw)
|
if (!bw)
|
||||||
bw = &bw_tmp;
|
bw = &bw_tmp;
|
||||||
|
@ -3912,10 +3918,7 @@ FRESULT f_write (
|
||||||
EFSPRINTF("FOV");
|
EFSPRINTF("FOV");
|
||||||
LEAVE_FF(fs, res); /* Check validity */
|
LEAVE_FF(fs, res); /* Check validity */
|
||||||
}
|
}
|
||||||
if (!(fp->flag & FA_WRITE)) {
|
if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
|
||||||
EFSPRINTF("NOACCESS");
|
|
||||||
LEAVE_FF(fs, FR_DENIED); /* Check access mode */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */
|
/* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */
|
||||||
if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
|
if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
|
||||||
|
@ -3961,15 +3964,12 @@ FRESULT f_write (
|
||||||
if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */
|
if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */
|
||||||
#else
|
#else
|
||||||
if (fp->flag & FA_DIRTY) { /* Write-back sector cache */
|
if (fp->flag & FA_DIRTY) { /* Write-back sector cache */
|
||||||
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK)
|
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
||||||
ABORT(fs, FR_DISK_ERR);
|
|
||||||
fp->flag &= (BYTE)~FA_DIRTY;
|
fp->flag &= (BYTE)~FA_DIRTY;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sect = clst2sect(fs, fp->clust); /* Get current sector */
|
sect = clst2sect(fs, fp->clust); /* Get current sector */
|
||||||
if (sect == 0) {
|
if (sect == 0) ABORT(fs, FR_INT_ERR);
|
||||||
ABORT(fs, FR_INT_ERR);
|
|
||||||
}
|
|
||||||
sect += csect;
|
sect += csect;
|
||||||
cc = btw / SS(fs); /* When remaining bytes >= sector size, */
|
cc = btw / SS(fs); /* When remaining bytes >= sector size, */
|
||||||
if (cc > 0) { /* Write maximum contiguous sectors directly */
|
if (cc > 0) { /* Write maximum contiguous sectors directly */
|
||||||
|
@ -4004,8 +4004,9 @@ FRESULT f_write (
|
||||||
#else
|
#else
|
||||||
if (fp->sect != sect && /* Fill sector cache with file data */
|
if (fp->sect != sect && /* Fill sector cache with file data */
|
||||||
fp->fptr < fp->obj.objsize &&
|
fp->fptr < fp->obj.objsize &&
|
||||||
disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK)
|
disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
|
||||||
ABORT(fs, FR_DISK_ERR);
|
ABORT(fs, FR_DISK_ERR);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
fp->sect = sect;
|
fp->sect = sect;
|
||||||
}
|
}
|
||||||
|
@ -4251,6 +4252,7 @@ FRESULT f_getcwd (
|
||||||
|
|
||||||
|
|
||||||
/* Get logical drive */
|
/* Get logical drive */
|
||||||
|
buff[0] = 0; /* Set null string to get current volume */
|
||||||
res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */
|
res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
dj.obj.fs = fs;
|
dj.obj.fs = fs;
|
||||||
|
@ -4269,7 +4271,7 @@ FRESULT f_getcwd (
|
||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
do { /* Find the entry links to the child directory */
|
do { /* Find the entry links to the child directory */
|
||||||
res = dir_read_file(&dj);
|
res = DIR_READ_FILE(&dj);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */
|
if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */
|
||||||
res = dir_next(&dj, 0);
|
res = dir_next(&dj, 0);
|
||||||
|
@ -4601,7 +4603,7 @@ FRESULT f_readdir (
|
||||||
res = dir_sdi(dp, 0); /* Rewind the directory object */
|
res = dir_sdi(dp, 0); /* Rewind the directory object */
|
||||||
} else {
|
} else {
|
||||||
INIT_NAMBUF(fs);
|
INIT_NAMBUF(fs);
|
||||||
res = dir_read_file(dp); /* Read an item */
|
res = DIR_READ_FILE(dp); /* Read an item */
|
||||||
if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */
|
if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */
|
||||||
if (res == FR_OK) { /* A valid entry is found */
|
if (res == FR_OK) { /* A valid entry is found */
|
||||||
get_fileinfo(dp, fno); /* Get the object information */
|
get_fileinfo(dp, fno); /* Get the object information */
|
||||||
|
@ -4746,7 +4748,7 @@ FRESULT f_getfree (
|
||||||
UINT b;
|
UINT b;
|
||||||
|
|
||||||
clst = fs->n_fatent - 2; /* Number of clusters */
|
clst = fs->n_fatent - 2; /* Number of clusters */
|
||||||
sect = fs->database; /* Assuming bitmap starts at cluster 2 */
|
sect = fs->bitbase; /* Bitmap sector */
|
||||||
i = 0; /* Offset in the sector */
|
i = 0; /* Offset in the sector */
|
||||||
do { /* Counts numbuer of bits with zero in the bitmap */
|
do { /* Counts numbuer of bits with zero in the bitmap */
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
|
@ -4909,7 +4911,7 @@ FRESULT f_unlink (
|
||||||
#endif
|
#endif
|
||||||
res = dir_sdi(&sdj, 0);
|
res = dir_sdi(&sdj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_file(&sdj); /* Test if the directory is empty */
|
res = DIR_READ_FILE(&sdj); /* Test if the directory is empty */
|
||||||
if (res == FR_OK) res = FR_DENIED; /* Not empty? */
|
if (res == FR_OK) res = FR_DENIED; /* Not empty? */
|
||||||
if (res == FR_NO_FILE) res = FR_OK; /* Empty? */
|
if (res == FR_NO_FILE) res = FR_OK; /* Empty? */
|
||||||
}
|
}
|
||||||
|
@ -4949,47 +4951,43 @@ FRESULT f_mkdir (
|
||||||
DIR dj;
|
DIR dj;
|
||||||
FFOBJID sobj;
|
FFOBJID sobj;
|
||||||
FATFS *fs;
|
FATFS *fs;
|
||||||
BYTE *dir;
|
|
||||||
DWORD dcl, pcl, tm;
|
DWORD dcl, pcl, tm;
|
||||||
DEF_NAMBUF
|
DEF_NAMBUF
|
||||||
|
|
||||||
|
|
||||||
/* Get logical drive */
|
res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */
|
||||||
res = find_volume(&path, &fs, FA_WRITE);
|
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
dj.obj.fs = fs;
|
dj.obj.fs = fs;
|
||||||
INIT_NAMBUF(fs);
|
INIT_NAMBUF(fs);
|
||||||
res = follow_path(&dj, path); /* Follow the file path */
|
res = follow_path(&dj, path); /* Follow the file path */
|
||||||
if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */
|
if (res == FR_OK) res = FR_EXIST; /* Name collision? */
|
||||||
if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) {
|
if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { /* Invalid name? */
|
||||||
res = FR_INVALID_NAME;
|
res = FR_INVALID_NAME;
|
||||||
}
|
}
|
||||||
if (res == FR_NO_FILE) { /* Can create a new directory */
|
if (res == FR_NO_FILE) { /* It is clear to create a new directory */
|
||||||
sobj.fs = fs; /* New object id to create a new chain */
|
sobj.fs = fs; /* New object id to create a new chain */
|
||||||
dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */
|
dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */
|
||||||
res = FR_OK;
|
res = FR_OK;
|
||||||
if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */
|
if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster? */
|
||||||
if (dcl == 1) res = FR_INT_ERR;
|
if (dcl == 1) res = FR_INT_ERR; /* Any insanity? */
|
||||||
if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
|
if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; /* Disk error? */
|
||||||
if (res == FR_OK) res = sync_window(fs); /* Flush FAT */
|
|
||||||
tm = GET_FATTIME();
|
tm = GET_FATTIME();
|
||||||
if (res == FR_OK) { /* Initialize the new directory table */
|
if (res == FR_OK) {
|
||||||
res = dir_clear(fs, dcl); /* Clean up the new table */
|
res = dir_clear(fs, dcl); /* Clean up the new table */
|
||||||
if (res == FR_OK && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT)) { /* Create dot entries (FAT only) */
|
if (res == FR_OK) {
|
||||||
dir = fs->win;
|
if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* Create dot entries (FAT only) */
|
||||||
mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */
|
mem_set(fs->win + DIR_Name, ' ', 11); /* Create "." entry */
|
||||||
dir[DIR_Name] = '.';
|
fs->win[DIR_Name] = '.';
|
||||||
dir[DIR_Attr] = AM_DIR;
|
fs->win[DIR_Attr] = AM_DIR;
|
||||||
st_dword(dir + DIR_ModTime, tm);
|
st_dword(fs->win + DIR_ModTime, tm);
|
||||||
st_clust(fs, dir, dcl);
|
st_clust(fs, fs->win, dcl);
|
||||||
mem_cpy(dir + SZDIRE, dir, SZDIRE); /* Create ".." entry */
|
mem_cpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */
|
||||||
dir[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
|
fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
|
||||||
st_clust(fs, dir + SZDIRE, pcl);
|
st_clust(fs, fs->win + SZDIRE, pcl);
|
||||||
fs->wflag = 1;
|
fs->wflag = 1;
|
||||||
}
|
}
|
||||||
|
res = dir_register(&dj); /* Register the object to the parent directoy */
|
||||||
}
|
}
|
||||||
if (res == FR_OK) {
|
|
||||||
res = dir_register(&dj); /* Register the object to the directoy */
|
|
||||||
}
|
}
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
|
@ -5004,17 +5002,16 @@ FRESULT f_mkdir (
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
dir = dj.dir;
|
st_dword(dj.dir + DIR_ModTime, tm); /* Created time */
|
||||||
st_dword(dir + DIR_ModTime, tm); /* Created time */
|
st_clust(fs, dj.dir, dcl); /* Table start cluster */
|
||||||
st_clust(fs, dir, dcl); /* Table start cluster */
|
dj.dir[DIR_Attr] = AM_DIR; /* Attribute */
|
||||||
dir[DIR_Attr] = AM_DIR; /* Attribute */
|
|
||||||
fs->wflag = 1;
|
fs->wflag = 1;
|
||||||
}
|
}
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = sync_fs(fs);
|
res = sync_fs(fs);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
remove_chain(&dj.obj, dcl, 0); /* Could not register, remove cluster chain */
|
remove_chain(&sobj, dcl, 0); /* Could not register, remove the allocated cluster */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FREE_NAMBUF();
|
FREE_NAMBUF();
|
||||||
|
@ -5254,7 +5251,7 @@ FRESULT f_getlabel (
|
||||||
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_label(&dj); /* Find a volume label entry */
|
res = DIR_READ_LABEL(&dj); /* Find a volume label entry */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) {
|
if (fs->fs_type == FS_EXFAT) {
|
||||||
|
@ -5399,7 +5396,7 @@ FRESULT f_setlabel (
|
||||||
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_label(&dj); /* Get volume label entry */
|
res = DIR_READ_LABEL(&dj); /* Get volume label entry */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
||||||
dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */
|
dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */
|
||||||
|
@ -5421,7 +5418,7 @@ FRESULT f_setlabel (
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */
|
mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */
|
||||||
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
||||||
dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */
|
dj.dir[XDIR_Type] = ET_VLABEL; /* Create volume label entry */
|
||||||
dj.dir[XDIR_NumLabel] = (BYTE)di;
|
dj.dir[XDIR_NumLabel] = (BYTE)di;
|
||||||
mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
|
mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5726,7 +5723,7 @@ FRESULT f_mkfs (
|
||||||
b_fat = b_vol + 32; /* FAT start at offset 32 */
|
b_fat = b_vol + 32; /* FAT start at offset 32 */
|
||||||
sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */
|
sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */
|
||||||
b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */
|
b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */
|
||||||
if (b_data >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */
|
if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */
|
||||||
n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */
|
n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */
|
||||||
if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */
|
if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */
|
||||||
if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */
|
if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */
|
||||||
|
@ -5807,11 +5804,11 @@ FRESULT f_mkfs (
|
||||||
|
|
||||||
/* Initialize the root directory */
|
/* Initialize the root directory */
|
||||||
mem_set(buf, 0, szb_buf);
|
mem_set(buf, 0, szb_buf);
|
||||||
buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */
|
buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry */
|
||||||
buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */
|
buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */
|
||||||
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
|
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
|
||||||
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
|
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
|
||||||
buf[SZDIRE * 2 + 0] = 0x82; /* 82 entry (up-case table) */
|
buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */
|
||||||
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
|
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
|
||||||
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */
|
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */
|
||||||
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
|
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
|
||||||
|
@ -6299,8 +6296,7 @@ typedef struct { /* Putchar output buffer and work area */
|
||||||
} putbuff;
|
} putbuff;
|
||||||
|
|
||||||
|
|
||||||
static
|
static void putc_bfd ( /* Buffered write with code conversion */
|
||||||
void putc_bfd ( /* Buffered write with code conversion */
|
|
||||||
putbuff* pb,
|
putbuff* pb,
|
||||||
TCHAR c
|
TCHAR c
|
||||||
)
|
)
|
||||||
|
@ -6411,7 +6407,7 @@ void putc_bfd ( /* Buffered write with code conversion */
|
||||||
#else /* Write it in ANSI/OEM */
|
#else /* Write it in ANSI/OEM */
|
||||||
if (hs != 0) return;
|
if (hs != 0) return;
|
||||||
wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */
|
wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */
|
||||||
if (wc == 0) return;;
|
if (wc == 0) return;
|
||||||
if (wc >= 0x100) {
|
if (wc >= 0x100) {
|
||||||
pb->buf[i++] = (BYTE)(wc >> 8); nc++;
|
pb->buf[i++] = (BYTE)(wc >> 8); nc++;
|
||||||
}
|
}
|
||||||
|
@ -6431,8 +6427,7 @@ void putc_bfd ( /* Buffered write with code conversion */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static int putc_flush ( /* Flush left characters in the buffer */
|
||||||
int putc_flush ( /* Flush left characters in the buffer */
|
|
||||||
putbuff* pb
|
putbuff* pb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -6445,8 +6440,7 @@ int putc_flush ( /* Flush left characters in the buffer */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static void putc_init ( /* Initialize write buffer */
|
||||||
void putc_init ( /* Initialize write buffer */
|
|
||||||
putbuff* pb,
|
putbuff* pb,
|
||||||
FIL* fp
|
FIL* fp
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - Generic FAT Filesystem module R0.13b /
|
/ FatFs - Generic FAT Filesystem module R0.13c /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2018, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
|
|
||||||
#ifndef FF_DEFINED
|
#ifndef FF_DEFINED
|
||||||
#define FF_DEFINED 63463 /* Revision ID */
|
#define FF_DEFINED 86604 /* Revision ID */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -95,8 +95,8 @@ typedef DWORD FSIZE_t;
|
||||||
/* Filesystem object structure (FATFS) */
|
/* Filesystem object structure (FATFS) */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE fs_type; /* Filesystem type (0:N/A) */
|
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||||
BYTE pdrv; /* Physical drive number */
|
BYTE pdrv; /* Associated physical drive */
|
||||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||||
BYTE wflag; /* win[] flag (b0:dirty) */
|
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||||
|
@ -133,6 +133,9 @@ typedef struct {
|
||||||
DWORD fatbase; /* FAT base sector */
|
DWORD fatbase; /* FAT base sector */
|
||||||
DWORD dirbase; /* Root directory base sector/cluster */
|
DWORD dirbase; /* Root directory base sector/cluster */
|
||||||
DWORD database; /* Data base sector */
|
DWORD database; /* Data base sector */
|
||||||
|
#if FF_FS_EXFAT
|
||||||
|
DWORD bitbase; /* Allocation bitmap base sector */
|
||||||
|
#endif
|
||||||
DWORD winsect; /* Current sector appearing in the win[] */
|
DWORD winsect; /* Current sector appearing in the win[] */
|
||||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||||
} FATFS;
|
} FATFS;
|
||||||
|
@ -145,7 +148,7 @@ typedef struct {
|
||||||
FATFS* fs; /* Pointer to the hosting volume of this object */
|
FATFS* fs; /* Pointer to the hosting volume of this object */
|
||||||
WORD id; /* Hosting volume mount ID */
|
WORD id; /* Hosting volume mount ID */
|
||||||
BYTE attr; /* Object attribute */
|
BYTE attr; /* Object attribute */
|
||||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */
|
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
|
||||||
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
||||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
|
@ -175,12 +178,12 @@ typedef struct {
|
||||||
DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
|
DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
|
||||||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
|
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
|
||||||
#endif
|
#endif
|
||||||
#if FF_USE_FASTSEEK
|
|
||||||
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
|
|
||||||
#endif
|
|
||||||
#if !FF_FS_TINY
|
#if !FF_FS_TINY
|
||||||
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
|
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
|
||||||
#endif
|
#endif
|
||||||
|
#if FF_USE_FASTSEEK
|
||||||
|
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
|
||||||
|
#endif
|
||||||
} FIL;
|
} FIL;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ FatFs - Configuration file
|
/ FatFs Functional Configurations
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define FFCONF_DEF 63463 /* Revision ID */
|
#define FFCONF_DEF 86604 /* Revision ID */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ Function Configurations
|
/ Function Configurations
|
||||||
|
@ -232,14 +232,14 @@
|
||||||
|
|
||||||
#define FF_FS_EXFAT 1
|
#define FF_FS_EXFAT 1
|
||||||
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
||||||
/ To enable exFAT, also LFN needs to be enabled.
|
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
|
||||||
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
||||||
|
|
||||||
|
|
||||||
#define FF_FS_NORTC 1
|
#define FF_FS_NORTC 1
|
||||||
#define FF_NORTC_MON 1
|
#define FF_NORTC_MON 1
|
||||||
#define FF_NORTC_MDAY 1
|
#define FF_NORTC_MDAY 1
|
||||||
#define FF_NORTC_YEAR 2018
|
#define FF_NORTC_YEAR 2019
|
||||||
/* The option FF_FS_NORTC switches timestamp function. If the system does not have
|
/* The option FF_FS_NORTC switches timestamp function. If the system does not have
|
||||||
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
|
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
|
||||||
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
|
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
|
||||||
|
@ -262,6 +262,7 @@
|
||||||
/ lock control is independent of re-entrancy. */
|
/ lock control is independent of re-entrancy. */
|
||||||
|
|
||||||
|
|
||||||
|
/* #include <somertos.h> // O/S definitions */
|
||||||
#define FF_FS_REENTRANT 0
|
#define FF_FS_REENTRANT 0
|
||||||
#define FF_FS_TIMEOUT 1000
|
#define FF_FS_TIMEOUT 1000
|
||||||
#define FF_SYNC_t HANDLE
|
#define FF_SYNC_t HANDLE
|
||||||
|
@ -282,8 +283,6 @@
|
||||||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
||||||
/ included somewhere in the scope of ff.h. */
|
/ included somewhere in the scope of ff.h. */
|
||||||
|
|
||||||
/* #include <windows.h> // O/S definitions */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--- End of configuration options ---*/
|
/*--- End of configuration options ---*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Sample Code of OS Dependent Functions for FatFs */
|
/* Sample Code of OS Dependent Functions for FatFs */
|
||||||
/* (C) ChaN, 2017 */
|
/* (C) ChaN, 2018 */
|
||||||
/* (C) CTCaer, 2018 */
|
/* (C) CTCaer, 2018 */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
/* Allocate a memory block */
|
/* Allocate a memory block */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */
|
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
|
||||||
UINT msize /* Number of bytes to allocate */
|
UINT msize /* Number of bytes to allocate */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on no
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void ff_memfree (
|
void ff_memfree (
|
||||||
void* mblock /* Pointer to the memory block to free (nothing to do for null) */
|
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
free(mblock); /* Free the memory block with POSIX API */
|
free(mblock); /* Free the memory block with POSIX API */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Unicode handling functions for FatFs R0.13a */
|
/* Unicode handling functions for FatFs R0.13c */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* This module will occupy a huge memory in the .const section when the /
|
/* This module will occupy a huge memory in the .const section when the /
|
||||||
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
|
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
/ that function to avoid silly memory consumption. /
|
/ that function to avoid silly memory consumption. /
|
||||||
/-------------------------------------------------------------------------*/
|
/-------------------------------------------------------------------------*/
|
||||||
/*
|
/*
|
||||||
/ Copyright (C) 2017, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
/
|
/
|
||||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||||
/ source and binary forms, with or without modification, are permitted provided
|
/ source and binary forms, with or without modification, are permitted provided
|
||||||
|
@ -25,9 +25,9 @@
|
||||||
|
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
#if FF_USE_LFN /* This module is blanked when non-LFN configuration */
|
#if FF_USE_LFN /* This module will be blanked at non-LFN configuration */
|
||||||
|
|
||||||
#if FF_DEFINED != 63463 /* Revision ID */
|
#if FF_DEFINED != 86604 /* Revision ID */
|
||||||
#error Wrong include file (ff.h).
|
#error Wrong include file (ff.h).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ SECTIONS {
|
||||||
. = __ipl_start;
|
. = __ipl_start;
|
||||||
.text : {
|
.text : {
|
||||||
*(.text._start);
|
*(.text._start);
|
||||||
. = . + 36;
|
*(._boot_cfg);
|
||||||
*(.text*);
|
*(.text*);
|
||||||
}
|
}
|
||||||
.data : {
|
.data : {
|
||||||
|
|
|
@ -25,11 +25,7 @@
|
||||||
#include "power/max77620.h"
|
#include "power/max77620.h"
|
||||||
#include "rtc/max77620-rtc.h"
|
#include "rtc/max77620-rtc.h"
|
||||||
#include "soc/hw_init.h"
|
#include "soc/hw_init.h"
|
||||||
#include "soc/i2c.h"
|
|
||||||
#include "soc/pmc.h"
|
|
||||||
#include "soc/t210.h"
|
|
||||||
#include "storage/sdmmc.h"
|
#include "storage/sdmmc.h"
|
||||||
#include "utils/btn.h"
|
|
||||||
#include "utils/util.h"
|
#include "utils/util.h"
|
||||||
|
|
||||||
#include "keys/keys.h"
|
#include "keys/keys.h"
|
||||||
|
@ -39,7 +35,7 @@ sdmmc_storage_t sd_storage;
|
||||||
FATFS sd_fs;
|
FATFS sd_fs;
|
||||||
static bool sd_mounted;
|
static bool sd_mounted;
|
||||||
|
|
||||||
boot_cfg_t *b_cfg;
|
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
|
||||||
|
|
||||||
bool sd_mount()
|
bool sd_mount()
|
||||||
{
|
{
|
||||||
|
@ -117,96 +113,53 @@ int sd_save_to_file(void *buf, u32 size, const char *filename)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
f_sync(&fp);
|
|
||||||
f_write(&fp, buf, size, NULL);
|
f_write(&fp, buf, size, NULL);
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void panic(u32 val)
|
|
||||||
{
|
|
||||||
// Set panic code.
|
|
||||||
PMC(APBDEV_PMC_SCRATCH200) = val;
|
|
||||||
//PMC(APBDEV_PMC_CRYPTO_OP) = 1; // Disable SE.
|
|
||||||
TMR(TIMER_WDT4_UNLOCK_PATTERN) = TIMER_MAGIC_PTRN;
|
|
||||||
TMR(TIMER_TMR9_TMR_PTV) = TIMER_EN | TIMER_PER_EN;
|
|
||||||
TMR(TIMER_WDT4_CONFIG) = TIMER_SRC(9) | TIMER_PER(1) | TIMER_PMCRESET_EN;
|
|
||||||
TMR(TIMER_WDT4_COMMAND) = TIMER_START_CNT;
|
|
||||||
while (1)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reboot_normal()
|
|
||||||
{
|
|
||||||
sd_unmount();
|
|
||||||
display_end();
|
|
||||||
panic(0x21); // Bypass fuse programming in package1.
|
|
||||||
}
|
|
||||||
|
|
||||||
void reboot_rcm()
|
|
||||||
{
|
|
||||||
sd_unmount();
|
|
||||||
display_end();
|
|
||||||
PMC(APBDEV_PMC_SCRATCH0) = 2; // Reboot into rcm.
|
|
||||||
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST;
|
|
||||||
while (true)
|
|
||||||
usleep(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void power_off()
|
|
||||||
{
|
|
||||||
sd_unmount();
|
|
||||||
max77620_rtc_stop_alarm();
|
|
||||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a safe and unused DRAM region for our payloads.
|
// This is a safe and unused DRAM region for our payloads.
|
||||||
// IPL_LOAD_ADDR is defined in makefile.
|
#define RELOC_META_OFF 0x7C
|
||||||
#define EXT_PAYLOAD_ADDR 0xC03C0000
|
|
||||||
#define PATCHED_RELOC_SZ 0x94
|
#define PATCHED_RELOC_SZ 0x94
|
||||||
#define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))
|
#define PATCHED_RELOC_STACK 0x40007000
|
||||||
#define PAYLOAD_ENTRY 0x40010000
|
|
||||||
#define CBFS_SDRAM_EN_ADDR 0x4003e000
|
|
||||||
#define COREBOOT_ADDR (0xD0000000 - 0x100000)
|
#define COREBOOT_ADDR (0xD0000000 - 0x100000)
|
||||||
|
#define CBFS_DRAM_EN_ADDR 0x4003e000
|
||||||
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
|
#define CBFS_DRAM_MAGIC 0x4452414D // "DRAM"
|
||||||
void (*update_ptr)() = (void *)RCM_PAYLOAD_ADDR;
|
|
||||||
|
|
||||||
void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size)
|
void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size)
|
||||||
{
|
{
|
||||||
static const u32 START_OFF = 0x7C;
|
|
||||||
static const u32 STACK_OFF = 0x80;
|
|
||||||
static const u32 PAYLOAD_END_OFF = 0x84;
|
|
||||||
static const u32 IPL_START_OFF = 0x88;
|
|
||||||
|
|
||||||
memcpy((u8 *)payload_src, (u8 *)IPL_LOAD_ADDR, PATCHED_RELOC_SZ);
|
memcpy((u8 *)payload_src, (u8 *)IPL_LOAD_ADDR, PATCHED_RELOC_SZ);
|
||||||
|
|
||||||
*(vu32 *)(payload_src + START_OFF) = payload_dst - ALIGN(PATCHED_RELOC_SZ, 0x10);
|
volatile reloc_meta_t *relocator = (reloc_meta_t *)(payload_src + RELOC_META_OFF);
|
||||||
*(vu32 *)(payload_src + PAYLOAD_END_OFF) = payload_dst + payload_size;
|
|
||||||
*(vu32 *)(payload_src + STACK_OFF) = 0x40008000;
|
relocator->start = payload_dst - ALIGN(PATCHED_RELOC_SZ, 0x10);
|
||||||
*(vu32 *)(payload_src + IPL_START_OFF) = payload_dst;
|
relocator->stack = PATCHED_RELOC_STACK;
|
||||||
|
relocator->end = payload_dst + payload_size;
|
||||||
|
relocator->ep = payload_dst;
|
||||||
|
|
||||||
if (payload_size == 0x7000)
|
if (payload_size == 0x7000)
|
||||||
{
|
{
|
||||||
memcpy((u8 *)(payload_src + ALIGN(PATCHED_RELOC_SZ, 0x10)), (u8 *)COREBOOT_ADDR, 0x7000); //Bootblock
|
memcpy((u8 *)(payload_src + ALIGN(PATCHED_RELOC_SZ, 0x10)), (u8 *)COREBOOT_ADDR, 0x7000); //Bootblock
|
||||||
*(vu32 *)CBFS_SDRAM_EN_ADDR = 0x4452414D;
|
*(vu32 *)CBFS_DRAM_EN_ADDR = CBFS_DRAM_MAGIC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define IPL_STACK_TOP 0x4003F000
|
||||||
|
#define IPL_HEAP_START 0x90020000
|
||||||
|
|
||||||
extern void pivot_stack(u32 stack_top);
|
extern void pivot_stack(u32 stack_top);
|
||||||
|
|
||||||
void ipl_main() {
|
void ipl_main() {
|
||||||
b_cfg = (boot_cfg_t *)(IPL_LOAD_ADDR + PATCHED_RELOC_SZ);
|
|
||||||
|
|
||||||
config_hw();
|
config_hw();
|
||||||
pivot_stack(0x4003F000);
|
pivot_stack(IPL_STACK_TOP);
|
||||||
heap_init(0x90020000);
|
heap_init(IPL_HEAP_START);
|
||||||
|
|
||||||
display_init();
|
display_init();
|
||||||
u32 *fb = display_init_framebuffer();
|
u32 *fb = display_init_framebuffer();
|
||||||
gfx_init_ctxt(&gfx_ctxt, fb, 720, 1280, 720);
|
gfx_init_ctxt(fb, 720, 1280, 720);
|
||||||
gfx_con_init(&gfx_con, &gfx_ctxt);
|
gfx_con_init();
|
||||||
display_backlight_pwm_init();
|
display_backlight_pwm_init();
|
||||||
|
|
||||||
sd_mount();
|
sd_mount();
|
||||||
|
|
|
@ -371,15 +371,15 @@ int se_calc_sha256(void *dst, const void *src, u32 src_size)
|
||||||
int res;
|
int res;
|
||||||
// Setup config for SHA256, size = BITS(src_size).
|
// Setup config for SHA256, size = BITS(src_size).
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
||||||
SE(SE_SHA_CONFIG_REG_OFFSET) = 1;
|
SE(SE_SHA_CONFIG_REG_OFFSET) = SHA_ENABLE;
|
||||||
SE(SE_SHA_MSG_LENGTH_REG_OFFSET) = (u32)(src_size << 3);
|
SE(SE_SHA_MSG_LENGTH_REG_OFFSET) = (u32)(src_size << 3);
|
||||||
SE(0x208) = 0;
|
SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 1) = 0;
|
||||||
SE(0x20C) = 0;
|
SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 2) = 0;
|
||||||
SE(0x210) = 0;
|
SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 3) = 0;
|
||||||
SE(SE_SHA_MSG_LEFT_REG_OFFSET) = (u32)(src_size << 3);
|
SE(SE_SHA_MSG_LEFT_REG_OFFSET) = (u32)(src_size << 3);
|
||||||
SE(0x218) = 0;
|
SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 1) = 0;
|
||||||
SE(0x21C) = 0;
|
SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 2) = 0;
|
||||||
SE(0x220) = 0;
|
SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 3) = 0;
|
||||||
|
|
||||||
// Trigger the operation.
|
// Trigger the operation.
|
||||||
res = _se_execute(OP_START, NULL, 0, src, src_size);
|
res = _se_execute(OP_START, NULL, 0, src, src_size);
|
||||||
|
|
|
@ -32,4 +32,5 @@ int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const vo
|
||||||
int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize, u32 num_secs);
|
int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize, u32 num_secs);
|
||||||
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
|
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||||
int se_calc_sha256(void *dst, const void *src, u32 src_size);
|
int se_calc_sha256(void *dst, const void *src, u32 src_size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -214,16 +214,16 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||||
smmu_deinit_for_tsec();
|
smmu_deinit_for_tsec();
|
||||||
|
|
||||||
// for (int i = 0; i < kidx; i++)
|
// for (int i = 0; i < kidx; i++)
|
||||||
// gfx_printf(&gfx_con, "key %08X\n", key[i]);
|
// gfx_printf("key %08X\n", key[i]);
|
||||||
|
|
||||||
// gfx_printf(&gfx_con, "cpuctl (%08X) mbox (%08X)\n", TSEC(TSEC_CPUCTL), TSEC(TSEC_STATUS));
|
// gfx_printf("cpuctl (%08X) mbox (%08X)\n", TSEC(TSEC_CPUCTL), TSEC(TSEC_STATUS));
|
||||||
|
|
||||||
// u32 errst = MC(MC_ERR_STATUS);
|
// u32 errst = MC(MC_ERR_STATUS);
|
||||||
// gfx_printf(&gfx_con, " MC %08X %08X %08X\n", MC(MC_INTSTATUS), errst, MC(MC_ERR_ADR));
|
// gfx_printf(" MC %08X %08X %08X\n", MC(MC_INTSTATUS), errst, MC(MC_ERR_ADR));
|
||||||
// gfx_printf(&gfx_con, " type: %02X\n", errst >> 28);
|
// gfx_printf(" type: %02X\n", errst >> 28);
|
||||||
// gfx_printf(&gfx_con, " smmu: %02X\n", (errst >> 25) & 3);
|
// gfx_printf(" smmu: %02X\n", (errst >> 25) & 3);
|
||||||
// gfx_printf(&gfx_con, " dir: %s\n", (errst >> 16) & 1 ? "W" : "R");
|
// gfx_printf(" dir: %s\n", (errst >> 16) & 1 ? "W" : "R");
|
||||||
// gfx_printf(&gfx_con, " cid: %02x\n", errst & 0xFF);
|
// gfx_printf(" cid: %02x\n", errst & 0xFF);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -276,12 +276,16 @@ static void _clock_sdmmc_set_reset(u32 id)
|
||||||
{
|
{
|
||||||
case SDMMC_1:
|
case SDMMC_1:
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC1_RST;
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC1_RST;
|
||||||
|
break;
|
||||||
case SDMMC_2:
|
case SDMMC_2:
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC2_RST;
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC2_RST;
|
||||||
|
break;
|
||||||
case SDMMC_3:
|
case SDMMC_3:
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = U_SET_SDMMC3_RST;
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = U_SET_SDMMC3_RST;
|
||||||
|
break;
|
||||||
case SDMMC_4:
|
case SDMMC_4:
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC4_RST;
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC4_RST;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,12 +295,16 @@ static void _clock_sdmmc_clear_reset(u32 id)
|
||||||
{
|
{
|
||||||
case SDMMC_1:
|
case SDMMC_1:
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC1_RST;
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC1_RST;
|
||||||
|
break;
|
||||||
case SDMMC_2:
|
case SDMMC_2:
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC2_RST;
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC2_RST;
|
||||||
|
break;
|
||||||
case SDMMC_3:
|
case SDMMC_3:
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = U_CLR_SDMMC3_RST;
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = U_CLR_SDMMC3_RST;
|
||||||
|
break;
|
||||||
case SDMMC_4:
|
case SDMMC_4:
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC4_RST;
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC4_RST;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,12 +330,16 @@ static void _clock_sdmmc_set_enable(u32 id)
|
||||||
{
|
{
|
||||||
case SDMMC_1:
|
case SDMMC_1:
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC1;
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC1;
|
||||||
|
break;
|
||||||
case SDMMC_2:
|
case SDMMC_2:
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC2;
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC2;
|
||||||
|
break;
|
||||||
case SDMMC_3:
|
case SDMMC_3:
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = U_SET_CLK_ENB_SDMMC3;
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = U_SET_CLK_ENB_SDMMC3;
|
||||||
|
break;
|
||||||
case SDMMC_4:
|
case SDMMC_4:
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC4;
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC4;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,12 +349,16 @@ static void _clock_sdmmc_clear_enable(u32 id)
|
||||||
{
|
{
|
||||||
case SDMMC_1:
|
case SDMMC_1:
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC1;
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC1;
|
||||||
|
break;
|
||||||
case SDMMC_2:
|
case SDMMC_2:
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC2;
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC2;
|
||||||
|
break;
|
||||||
case SDMMC_3:
|
case SDMMC_3:
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = U_CLR_CLK_ENB_SDMMC3;
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = U_CLR_CLK_ENB_SDMMC3;
|
||||||
|
break;
|
||||||
case SDMMC_4:
|
case SDMMC_4:
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC4;
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC4;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,6 +473,7 @@ void clock_sdmmc_get_params(u32 *pout, u16 *pdivisor, u32 type)
|
||||||
case 5:
|
case 5:
|
||||||
*pout = 25000;
|
*pout = 25000;
|
||||||
*pdivisor = 64;
|
*pdivisor = 64;
|
||||||
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
case 8:
|
case 8:
|
||||||
*pout = 25000;
|
*pout = 25000;
|
||||||
|
@ -465,9 +482,11 @@ void clock_sdmmc_get_params(u32 *pout, u16 *pdivisor, u32 type)
|
||||||
case 7:
|
case 7:
|
||||||
*pout = 50000;
|
*pout = 50000;
|
||||||
*pdivisor = 1;
|
*pdivisor = 1;
|
||||||
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
*pout = 100000;
|
*pout = 100000;
|
||||||
*pdivisor = 1;
|
*pdivisor = 1;
|
||||||
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
*pout = 40800;
|
*pout = 40800;
|
||||||
*pdivisor = 1;
|
*pdivisor = 1;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018 shuffle2
|
* Copyright (c) 2018 shuffle2
|
||||||
* Copyright (c) 2018 balika011
|
* Copyright (c) 2018 balika011
|
||||||
|
* Copyright (c) 2019 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
@ -21,34 +22,6 @@
|
||||||
#include "../soc/fuse.h"
|
#include "../soc/fuse.h"
|
||||||
#include "../soc/t210.h"
|
#include "../soc/t210.h"
|
||||||
|
|
||||||
#define ARRAYSIZE(x) (sizeof(x) / sizeof(*x))
|
|
||||||
|
|
||||||
static const u32 evp_thunk_template[] = {
|
|
||||||
0xe92d0007, // STMFD SP!, {R0-R2}
|
|
||||||
0xe1a0200e, // MOV R2, LR
|
|
||||||
0xe2422002, // SUB R2, R2, #2
|
|
||||||
0xe5922000, // LDR R2, [R2]
|
|
||||||
0xe20220ff, // AND R2, R2, #0xFF
|
|
||||||
0xe1a02082, // MOV R2, R2,LSL#1
|
|
||||||
0xe59f001c, // LDR R0, =evp_thunk_template
|
|
||||||
0xe59f101c, // LDR R1, =thunk_end
|
|
||||||
0xe0411000, // SUB R1, R1, R0
|
|
||||||
0xe59f0018, // LDR R0, =iram_evp_thunks
|
|
||||||
0xe0800001, // ADD R0, R0, R1
|
|
||||||
0xe0822000, // ADD R2, R2, R0
|
|
||||||
0xe3822001, // ORR R2, R2, #1
|
|
||||||
0xe8bd0003, // LDMFD SP!, {R0,R1}
|
|
||||||
0xe12fff12, // BX R2
|
|
||||||
0x001007b0, // off_1007EC DCD evp_thunk_template
|
|
||||||
0x001007f8, // off_1007F0 DCD thunk_end
|
|
||||||
0x40004c30, // off_1007F4 DCD iram_evp_thunks
|
|
||||||
// thunk_end is here
|
|
||||||
};
|
|
||||||
static const u32 evp_thunk_template_len = sizeof(evp_thunk_template);
|
|
||||||
|
|
||||||
// treated as 12bit values
|
|
||||||
static const u32 hash_vals[] = {1, 2, 4, 8, 0, 3, 5, 6, 7, 9, 10, 11};
|
|
||||||
|
|
||||||
void fuse_disable_program()
|
void fuse_disable_program()
|
||||||
{
|
{
|
||||||
FUSE(FUSE_DISABLEREGPROGRAM) = 1;
|
FUSE(FUSE_DISABLEREGPROGRAM) = 1;
|
||||||
|
@ -58,268 +31,3 @@ u32 fuse_read_odm(u32 idx)
|
||||||
{
|
{
|
||||||
return FUSE(FUSE_RESERVED_ODMX(idx));
|
return FUSE(FUSE_RESERVED_ODMX(idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
void fuse_wait_idle()
|
|
||||||
{
|
|
||||||
u32 ctrl;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ctrl = FUSE(FUSE_CTRL);
|
|
||||||
} while (((ctrl >> 16) & 0x1f) != 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 parity32_even(u32 *words, u32 count)
|
|
||||||
{
|
|
||||||
u32 acc = words[0];
|
|
||||||
for (u32 i = 1; i < count; i++)
|
|
||||||
{
|
|
||||||
acc ^= words[i];
|
|
||||||
}
|
|
||||||
u32 lo = ((acc & 0xffff) ^ (acc >> 16)) & 0xff;
|
|
||||||
u32 hi = ((acc & 0xffff) ^ (acc >> 16)) >> 8;
|
|
||||||
u32 x = hi ^ lo;
|
|
||||||
lo = ((x & 0xf) ^ (x >> 4)) & 3;
|
|
||||||
hi = ((x & 0xf) ^ (x >> 4)) >> 2;
|
|
||||||
x = hi ^ lo;
|
|
||||||
|
|
||||||
return (x & 1) ^ (x >> 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int patch_hash_one(u32 *word)
|
|
||||||
{
|
|
||||||
u32 bits20_31 = *word & 0xfff00000;
|
|
||||||
u32 parity_bit = parity32_even(&bits20_31, 1);
|
|
||||||
u32 hash = 0;
|
|
||||||
for (u32 i = 0; i < 12; i++)
|
|
||||||
{
|
|
||||||
if (*word & (1 << (20 + i)))
|
|
||||||
{
|
|
||||||
hash ^= hash_vals[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hash == 0)
|
|
||||||
{
|
|
||||||
if (parity_bit == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*word ^= 1 << 24;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (parity_bit == 0)
|
|
||||||
{
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
for (u32 i = 0; i < ARRAYSIZE(hash_vals); i++)
|
|
||||||
{
|
|
||||||
if (hash_vals[i] == hash)
|
|
||||||
{
|
|
||||||
*word ^= 1 << (20 + i);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int patch_hash_multi(u32 *words, u32 count)
|
|
||||||
{
|
|
||||||
u32 parity_bit = parity32_even(words, count);
|
|
||||||
u32 bits0_14 = words[0] & 0x7fff;
|
|
||||||
u32 bit15 = words[0] & 0x8000;
|
|
||||||
u32 bits16_19 = words[0] & 0xf0000;
|
|
||||||
|
|
||||||
u32 hash = 0;
|
|
||||||
words[0] = bits16_19;
|
|
||||||
for (u32 i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
u32 w = words[i];
|
|
||||||
if (w)
|
|
||||||
{
|
|
||||||
for (u32 bitpos = 0; bitpos < 32; bitpos++)
|
|
||||||
{
|
|
||||||
if ((w >> bitpos) & 1)
|
|
||||||
{
|
|
||||||
hash ^= 0x4000 + i * 32 + bitpos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hash ^= bits0_14;
|
|
||||||
// stupid but this is what original code does.
|
|
||||||
// equivalent to original words[0] &= 0xfff00000
|
|
||||||
words[0] = bits16_19 ^ bit15 ^ bits0_14;
|
|
||||||
|
|
||||||
if (hash == 0)
|
|
||||||
{
|
|
||||||
if (parity_bit == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
words[0] ^= 0x8000;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (parity_bit == 0)
|
|
||||||
{
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
u32 bitcount = hash - 0x4000;
|
|
||||||
if (bitcount < 16 || bitcount >= count * 32)
|
|
||||||
{
|
|
||||||
u32 num_set = 0;
|
|
||||||
for (u32 bitpos = 0; bitpos < 15; bitpos++)
|
|
||||||
{
|
|
||||||
if ((hash >> bitpos) & 1)
|
|
||||||
{
|
|
||||||
num_set++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (num_set != 1)
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
words[0] ^= hash;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
words[bitcount / 32] ^= 1 << (hash & 0x1f);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
|
|
||||||
{
|
|
||||||
u32 words[80];
|
|
||||||
u32 word_count;
|
|
||||||
u32 word_addr;
|
|
||||||
u32 word0 = 0;
|
|
||||||
u32 total_read = 0;
|
|
||||||
|
|
||||||
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
|
|
||||||
word_count &= 0x7f;
|
|
||||||
word_addr = 191;
|
|
||||||
|
|
||||||
while (word_count)
|
|
||||||
{
|
|
||||||
total_read += word_count;
|
|
||||||
if (total_read >= ARRAYSIZE(words))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < word_count; i++)
|
|
||||||
{
|
|
||||||
FUSE(FUSE_ADDR) = word_addr--;
|
|
||||||
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
|
|
||||||
fuse_wait_idle();
|
|
||||||
words[i] = FUSE(FUSE_RDATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
word0 = words[0];
|
|
||||||
if (patch_hash_multi(words, word_count) >= 2)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
u32 ipatch_count = (words[0] >> 16) & 0xf;
|
|
||||||
if (ipatch_count)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < ipatch_count; i++)
|
|
||||||
{
|
|
||||||
u32 word = words[i + 1];
|
|
||||||
u32 addr = (word >> 16) * 2;
|
|
||||||
u32 data = word & 0xffff;
|
|
||||||
|
|
||||||
ipatch(addr, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
words[0] = word0;
|
|
||||||
if ((word0 >> 25) == 0)
|
|
||||||
break;
|
|
||||||
if (patch_hash_one(&word0) >= 2)
|
|
||||||
{
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
word_count = word0 >> 25;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
|
|
||||||
{
|
|
||||||
u32 words[80];
|
|
||||||
u32 word_count;
|
|
||||||
u32 word_addr;
|
|
||||||
u32 word0 = 0;
|
|
||||||
u32 total_read = 0;
|
|
||||||
int evp_thunk_written = 0;
|
|
||||||
void *evp_thunk_dst_addr = 0;
|
|
||||||
|
|
||||||
memset(iram_evp_thunks, 0, *iram_evp_thunks_len);
|
|
||||||
|
|
||||||
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
|
|
||||||
word_count &= 0x7f;
|
|
||||||
word_addr = 191;
|
|
||||||
|
|
||||||
while (word_count)
|
|
||||||
{
|
|
||||||
total_read += word_count;
|
|
||||||
if (total_read >= ARRAYSIZE(words))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < word_count; i++)
|
|
||||||
{
|
|
||||||
FUSE(FUSE_ADDR) = word_addr--;
|
|
||||||
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
|
|
||||||
fuse_wait_idle();
|
|
||||||
words[i] = FUSE(FUSE_RDATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
word0 = words[0];
|
|
||||||
if (patch_hash_multi(words, word_count) >= 2)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
u32 ipatch_count = (words[0] >> 16) & 0xf;
|
|
||||||
u32 insn_count = word_count - ipatch_count - 1;
|
|
||||||
if (insn_count)
|
|
||||||
{
|
|
||||||
if (!evp_thunk_written)
|
|
||||||
{
|
|
||||||
evp_thunk_dst_addr = (void *)iram_evp_thunks;
|
|
||||||
|
|
||||||
memcpy(evp_thunk_dst_addr, (void *)evp_thunk_template, evp_thunk_template_len);
|
|
||||||
evp_thunk_dst_addr += evp_thunk_template_len;
|
|
||||||
evp_thunk_written = 1;
|
|
||||||
*iram_evp_thunks_len = evp_thunk_template_len;
|
|
||||||
|
|
||||||
//write32(TEGRA_EXCEPTION_VECTORS_BASE + 0x208, iram_evp_thunks);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 thunk_patch_len = insn_count * sizeof(u32);
|
|
||||||
memcpy(evp_thunk_dst_addr, &words[ipatch_count + 1], thunk_patch_len);
|
|
||||||
evp_thunk_dst_addr += thunk_patch_len;
|
|
||||||
*iram_evp_thunks_len += thunk_patch_len;
|
|
||||||
}
|
|
||||||
words[0] = word0;
|
|
||||||
if ((word0 >> 25) == 0)
|
|
||||||
break;
|
|
||||||
if (patch_hash_one(&word0) >= 2)
|
|
||||||
{
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
word_count = word0 >> 25;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_raw_ipatch_fuses(u32 *words)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < 0x100; i++)
|
|
||||||
{
|
|
||||||
FUSE(FUSE_ADDR) = i;
|
|
||||||
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
|
|
||||||
fuse_wait_idle();
|
|
||||||
words[i] = FUSE(FUSE_RDATA);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -42,6 +42,7 @@
|
||||||
#define FUSE_PRIVATE_KEY1 0x1A8
|
#define FUSE_PRIVATE_KEY1 0x1A8
|
||||||
#define FUSE_PRIVATE_KEY2 0x1AC
|
#define FUSE_PRIVATE_KEY2 0x1AC
|
||||||
#define FUSE_PRIVATE_KEY3 0x1B0
|
#define FUSE_PRIVATE_KEY3 0x1B0
|
||||||
|
#define FUSE_RESERVED_SW 0x1C0
|
||||||
|
|
||||||
/*! Fuse commands. */
|
/*! Fuse commands. */
|
||||||
#define FUSE_READ 0x1
|
#define FUSE_READ 0x1
|
||||||
|
@ -54,9 +55,5 @@
|
||||||
|
|
||||||
void fuse_disable_program();
|
void fuse_disable_program();
|
||||||
u32 fuse_read_odm(u32 idx);
|
u32 fuse_read_odm(u32 idx);
|
||||||
void fuse_wait_idle();
|
|
||||||
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value));
|
|
||||||
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);
|
|
||||||
void read_raw_ipatch_fuses(u32 *words);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "../utils/util.h"
|
#include "../utils/util.h"
|
||||||
|
|
||||||
extern sdmmc_t sd_sdmmc;
|
extern sdmmc_t sd_sdmmc;
|
||||||
extern boot_cfg_t *b_cfg;
|
extern boot_cfg_t b_cfg;
|
||||||
|
|
||||||
void _config_oscillators()
|
void _config_oscillators()
|
||||||
{
|
{
|
||||||
|
@ -140,7 +140,7 @@ void _mbist_workaround()
|
||||||
void _config_se_brom()
|
void _config_se_brom()
|
||||||
{
|
{
|
||||||
// Skip SBK/SSK if sept was run.
|
// Skip SBK/SSK if sept was run.
|
||||||
if (!(b_cfg->boot_cfg & BOOT_CFG_SEPT_RUN))
|
if (!(b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN))
|
||||||
{
|
{
|
||||||
// Bootrom part we skipped.
|
// Bootrom part we skipped.
|
||||||
u32 sbk[4] = {
|
u32 sbk[4] = {
|
||||||
|
@ -161,7 +161,7 @@ void _config_se_brom()
|
||||||
|
|
||||||
// This memset needs to happen here, else TZRAM will behave weirdly later on.
|
// This memset needs to happen here, else TZRAM will behave weirdly later on.
|
||||||
memset((void *)TZRAM_BASE, 0, 0x10000);
|
memset((void *)TZRAM_BASE, 0, 0x10000);
|
||||||
PMC(APBDEV_PMC_CRYPTO_OP) = 0;
|
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
|
||||||
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F;
|
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F;
|
||||||
|
|
||||||
// Clear the boot reason to avoid problems later
|
// Clear the boot reason to avoid problems later
|
||||||
|
@ -227,6 +227,9 @@ void config_hw()
|
||||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2);
|
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2);
|
||||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2);
|
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2);
|
||||||
|
|
||||||
|
// Disable low battery shutdown monitor.
|
||||||
|
max77620_low_battery_monitor_config();
|
||||||
|
|
||||||
_config_pmc_scratch(); // Missing from 4.x+
|
_config_pmc_scratch(); // Missing from 4.x+
|
||||||
|
|
||||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = (CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888) | 0x3333;
|
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = (CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888) | 0x3333;
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#define PMC_PWR_DET_SDMMC1_IO_EN (1 << 12)
|
#define PMC_PWR_DET_SDMMC1_IO_EN (1 << 12)
|
||||||
#define APBDEV_PMC_DDR_PWR 0xE8
|
#define APBDEV_PMC_DDR_PWR 0xE8
|
||||||
#define APBDEV_PMC_CRYPTO_OP 0xF4
|
#define APBDEV_PMC_CRYPTO_OP 0xF4
|
||||||
|
#define PMC_CRYPTO_OP_SE_ENABLE 0
|
||||||
|
#define PMC_CRYPTO_OP_SE_DISABLE 1
|
||||||
#define APBDEV_PMC_SCRATCH33 0x120
|
#define APBDEV_PMC_SCRATCH33 0x120
|
||||||
#define APBDEV_PMC_SCRATCH40 0x13C
|
#define APBDEV_PMC_SCRATCH40 0x13C
|
||||||
#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4
|
#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4
|
||||||
|
|
|
@ -179,8 +179,13 @@
|
||||||
#define I2S_CG_SLCG_ENABLE (1 << 0)
|
#define I2S_CG_SLCG_ENABLE (1 << 0)
|
||||||
#define I2S_CTRL_MASTER_EN (1 << 10)
|
#define I2S_CTRL_MASTER_EN (1 << 10)
|
||||||
|
|
||||||
|
/*! PWM registers. */
|
||||||
|
#define PWM_CONTROLLER_PWM_CSR_0 0x00
|
||||||
|
#define PWM_CONTROLLER_PWM_CSR_1 0x10
|
||||||
|
|
||||||
/*! Special registers. */
|
/*! Special registers. */
|
||||||
#define EMC_SCRATCH0 0x324
|
#define EMC_SCRATCH0 0x324
|
||||||
|
#define EMC_HEKA_UPD (1 << 30)
|
||||||
#define EMC_SEPT_RUN (1 << 31)
|
#define EMC_SEPT_RUN (1 << 31)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -59,7 +59,7 @@ typedef struct _emmc_part_t
|
||||||
u32 lba_start;
|
u32 lba_start;
|
||||||
u32 lba_end;
|
u32 lba_end;
|
||||||
u64 attrs;
|
u64 attrs;
|
||||||
s8 name[37];
|
char name[37];
|
||||||
link_t link;
|
link_t link;
|
||||||
} emmc_part_t;
|
} emmc_part_t;
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "../mem/heap.h"
|
#include "../mem/heap.h"
|
||||||
|
|
||||||
/*#include "gfx.h"
|
/*#include "gfx.h"
|
||||||
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/
|
#define DPRINTF(...) gfx_printf(__VA_ARGS__)*/
|
||||||
#define DPRINTF(...)
|
#define DPRINTF(...)
|
||||||
|
|
||||||
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
||||||
|
@ -519,7 +519,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||||
free(ext_csd);
|
free(ext_csd);
|
||||||
DPRINTF("[MMC] got ext_csd\n");
|
DPRINTF("[MMC] got ext_csd\n");
|
||||||
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
|
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
|
||||||
//gfx_hexdump(&gfx_con, 0, ext_csd, 512);
|
//gfx_hexdump(0, ext_csd, 512);
|
||||||
|
|
||||||
/* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status.
|
/* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status.
|
||||||
Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end().
|
Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end().
|
||||||
|
@ -713,7 +713,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
||||||
storage->raw_scr[i] = buf[i + 3];
|
storage->raw_scr[i] = buf[i + 3];
|
||||||
}
|
}
|
||||||
_sd_storage_parse_scr(storage);
|
_sd_storage_parse_scr(storage);
|
||||||
//gfx_hexdump(&gfx_con, 0, storage->raw_scr, 8);
|
//gfx_hexdump(0, storage->raw_scr, 8);
|
||||||
|
|
||||||
return _sdmmc_storage_check_result(tmp);
|
return _sdmmc_storage_check_result(tmp);
|
||||||
}
|
}
|
||||||
|
@ -825,7 +825,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
|
||||||
|
|
||||||
if (!_sd_storage_switch_get(storage, buf))
|
if (!_sd_storage_switch_get(storage, buf))
|
||||||
return 0;
|
return 0;
|
||||||
//gfx_hexdump(&gfx_con, 0, (u8 *)buf, 64);
|
//gfx_hexdump(0, (u8 *)buf, 64);
|
||||||
|
|
||||||
u32 hs_type = 0;
|
u32 hs_type = 0;
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -875,7 +875,7 @@ int _sd_storage_enable_highspeed_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
||||||
{
|
{
|
||||||
if (!_sd_storage_switch_get(storage, buf))
|
if (!_sd_storage_switch_get(storage, buf))
|
||||||
return 0;
|
return 0;
|
||||||
//gfx_hexdump(&gfx_con, 0, (u8 *)buf, 64);
|
//gfx_hexdump(0, (u8 *)buf, 64);
|
||||||
if (!(buf[13] & 2))
|
if (!(buf[13] & 2))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -963,7 +963,7 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
||||||
storage->raw_ssr[i] = buf[i + 3];
|
storage->raw_ssr[i] = buf[i + 3];
|
||||||
}
|
}
|
||||||
_sd_storage_parse_ssr(storage);
|
_sd_storage_parse_ssr(storage);
|
||||||
//gfx_hexdump(&gfx_con, 0, storage->raw_ssr, 64);
|
//gfx_hexdump(0, storage->raw_ssr, 64);
|
||||||
|
|
||||||
return _sdmmc_storage_check_result(tmp);
|
return _sdmmc_storage_check_result(tmp);
|
||||||
}
|
}
|
||||||
|
@ -1088,7 +1088,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//gfx_hexdump(&gfx_con, 0, storage->raw_scr, 8);
|
//gfx_hexdump(0, storage->raw_scr, 8);
|
||||||
DPRINTF("[SD] got scr\n");
|
DPRINTF("[SD] got scr\n");
|
||||||
|
|
||||||
// Check if card supports a wider bus and if it's not SD Version 1.X
|
// Check if card supports a wider bus and if it's not SD Version 1.X
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "../soc/gpio.h"
|
#include "../soc/gpio.h"
|
||||||
|
|
||||||
/*#include "gfx.h"
|
/*#include "gfx.h"
|
||||||
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/
|
#define DPRINTF(...) gfx_printf(__VA_ARGS__)*/
|
||||||
#define DPRINTF(...)
|
#define DPRINTF(...)
|
||||||
|
|
||||||
/*! SCMMC controller base addresses. */
|
/*! SCMMC controller base addresses. */
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "../power/max77620.h"
|
#include "../power/max77620.h"
|
||||||
|
|
||||||
u32 btn_read()
|
u8 btn_read()
|
||||||
{
|
{
|
||||||
u32 res = 0;
|
u8 res = 0;
|
||||||
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_7))
|
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_7))
|
||||||
res |= BTN_VOL_DOWN;
|
res |= BTN_VOL_DOWN;
|
||||||
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
|
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
|
||||||
|
@ -34,9 +34,9 @@ u32 btn_read()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 btn_wait()
|
u8 btn_wait()
|
||||||
{
|
{
|
||||||
u32 res = 0, btn = btn_read();
|
u8 res = 0, btn = btn_read();
|
||||||
bool pwr = false;
|
bool pwr = false;
|
||||||
|
|
||||||
//Power button down, raise a filter.
|
//Power button down, raise a filter.
|
||||||
|
@ -59,16 +59,18 @@ u32 btn_wait()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 btn_wait_timeout(u32 time_ms, u32 mask)
|
u8 btn_wait_timeout(u32 time_ms, u8 mask)
|
||||||
{
|
{
|
||||||
u32 timeout = get_tmr_ms() + time_ms;
|
u32 timeout = get_tmr_ms() + time_ms;
|
||||||
u32 res = btn_read() & mask;
|
u8 res = btn_read() & mask;
|
||||||
|
|
||||||
do
|
while (get_tmr_ms() < timeout)
|
||||||
{
|
{
|
||||||
if (!(res & mask))
|
if (res == mask)
|
||||||
|
break;
|
||||||
|
else
|
||||||
res = btn_read() & mask;
|
res = btn_read() & mask;
|
||||||
} while (get_tmr_ms() < timeout);
|
};
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,12 @@
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define BTN_POWER 0x1
|
#define BTN_POWER (1 << 0)
|
||||||
#define BTN_VOL_DOWN 0x2
|
#define BTN_VOL_DOWN (1 << 1)
|
||||||
#define BTN_VOL_UP 0x4
|
#define BTN_VOL_UP (1 << 2)
|
||||||
|
|
||||||
u32 btn_read();
|
u8 btn_read();
|
||||||
u32 btn_wait();
|
u8 btn_wait();
|
||||||
u32 btn_wait_timeout(u32 time_ms, u32 mask);
|
u8 btn_wait_timeout(u32 time_ms, u8 mask);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
#define COLOR_BLUE 0xFF00DDFF
|
#define COLOR_BLUE 0xFF00DDFF
|
||||||
#define COLOR_VIOLET 0xFF8040FF
|
#define COLOR_VIOLET 0xFF8040FF
|
||||||
|
|
||||||
typedef char s8;
|
typedef signed char s8;
|
||||||
typedef short s16;
|
typedef short s16;
|
||||||
typedef short SHORT;
|
typedef short SHORT;
|
||||||
typedef int s32;
|
typedef int s32;
|
||||||
|
@ -79,8 +79,16 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t
|
||||||
u8 boot_cfg;
|
u8 boot_cfg;
|
||||||
u8 autoboot;
|
u8 autoboot;
|
||||||
u8 autoboot_list;
|
u8 autoboot_list;
|
||||||
u8 rsvd_cfg;
|
u8 extra_cfg;
|
||||||
u8 rsvd[32];
|
u8 rsvd[128];
|
||||||
} boot_cfg_t;
|
} boot_cfg_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__((__packed__)) _reloc_meta_t
|
||||||
|
{
|
||||||
|
u32 start;
|
||||||
|
u32 stack;
|
||||||
|
u32 end;
|
||||||
|
u32 ep;
|
||||||
|
} reloc_meta_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,8 +16,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "../gfx/di.h"
|
||||||
|
#include "../power/max77620.h"
|
||||||
|
#include "../rtc/max77620-rtc.h"
|
||||||
|
#include "../soc/i2c.h"
|
||||||
|
#include "../soc/pmc.h"
|
||||||
#include "../soc/t210.h"
|
#include "../soc/t210.h"
|
||||||
|
|
||||||
|
extern void sd_unmount();
|
||||||
|
|
||||||
u32 get_tmr_s()
|
u32 get_tmr_s()
|
||||||
{
|
{
|
||||||
return RTC(APBDEV_RTC_SECONDS);
|
return RTC(APBDEV_RTC_SECONDS);
|
||||||
|
@ -26,7 +33,7 @@ u32 get_tmr_s()
|
||||||
u32 get_tmr_ms()
|
u32 get_tmr_ms()
|
||||||
{
|
{
|
||||||
// The registers must be read with the following order:
|
// The registers must be read with the following order:
|
||||||
// -> RTC_MILLI_SECONDS (0x10) -> RTC_SHADOW_SECONDS (0xC)
|
// RTC_MILLI_SECONDS (0x10) -> RTC_SHADOW_SECONDS (0xC)
|
||||||
return (RTC(APBDEV_RTC_MILLI_SECONDS) | (RTC(APBDEV_RTC_SHADOW_SECONDS) << 10));
|
return (RTC(APBDEV_RTC_MILLI_SECONDS) | (RTC(APBDEV_RTC_SHADOW_SECONDS) << 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +63,50 @@ void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops)
|
||||||
base[ops[i].off] = ops[i].val;
|
base[ops[i].off] = ops[i].val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void panic(u32 val)
|
||||||
|
{
|
||||||
|
// Set panic code.
|
||||||
|
PMC(APBDEV_PMC_SCRATCH200) = val;
|
||||||
|
//PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_DISABLE;
|
||||||
|
TMR(TIMER_WDT4_UNLOCK_PATTERN) = TIMER_MAGIC_PTRN;
|
||||||
|
TMR(TIMER_TMR9_TMR_PTV) = TIMER_EN | TIMER_PER_EN;
|
||||||
|
TMR(TIMER_WDT4_CONFIG) = TIMER_SRC(9) | TIMER_PER(1) | TIMER_PMCRESET_EN;
|
||||||
|
TMR(TIMER_WDT4_COMMAND) = TIMER_START_CNT;
|
||||||
|
while (1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reboot_normal()
|
||||||
|
{
|
||||||
|
sd_unmount();
|
||||||
|
display_end();
|
||||||
|
|
||||||
|
panic(0x21); // Bypass fuse programming in package1.
|
||||||
|
}
|
||||||
|
|
||||||
|
void reboot_rcm()
|
||||||
|
{
|
||||||
|
sd_unmount();
|
||||||
|
display_end();
|
||||||
|
|
||||||
|
PMC(APBDEV_PMC_SCRATCH0) = 2; // Reboot into rcm.
|
||||||
|
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
usleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void power_off()
|
||||||
|
{
|
||||||
|
sd_unmount();
|
||||||
|
|
||||||
|
// Stop the alarm, in case we injected and powered off too fast.
|
||||||
|
max77620_rtc_stop_alarm();
|
||||||
|
|
||||||
|
//TODO: we should probably make sure all regulators are powered off properly.
|
||||||
|
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
#define CRC32C_POLY 0x82F63B78
|
#define CRC32C_POLY 0x82F63B78
|
||||||
u32 crc32c(const void *buf, u32 len)
|
u32 crc32c(const void *buf, u32 len)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define byte_swap_32(num) ((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \
|
#define byte_swap_32(num) (((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \
|
||||||
((num >> 8 )& 0xff00) | ((num << 24) & 0xff000000)
|
((num >> 8 )& 0xff00) | ((num << 24) & 0xff000000))
|
||||||
|
|
||||||
typedef struct _cfg_op_t
|
typedef struct _cfg_op_t
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,10 @@ u32 get_tmr_ms();
|
||||||
u32 get_tmr_s();
|
u32 get_tmr_s();
|
||||||
void usleep(u32 ticks);
|
void usleep(u32 ticks);
|
||||||
void msleep(u32 milliseconds);
|
void msleep(u32 milliseconds);
|
||||||
|
void panic(u32 val);
|
||||||
|
void reboot_normal();
|
||||||
|
void reboot_rcm();
|
||||||
|
void power_off();
|
||||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
||||||
u32 crc32c(const void *buf, u32 len);
|
u32 crc32c(const void *buf, u32 len);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue