diff --git a/include/PR/bbcard.h b/include/PR/bbcard.h new file mode 100644 index 00000000..5061d357 --- /dev/null +++ b/include/PR/bbcard.h @@ -0,0 +1,35 @@ +#ifndef _BBCARD_H_ +#define _BBCARD_H_ + +#include "ultratypes.h" +#include "bbnand.h" + +#define BBCARD_ERR_NO_CARD (-1) /* no card present */ +#define BBCARD_ERR_FAIL (-2) /* operation failed */ +#define BBCARD_ERR_INVALID (-3) /* invalid parameters */ +#define BBCARD_ERR_CHANGED (-4) /* card changed */ + +void osBbCardInit(void); +s32 osBbCardReadBlock(u32 dev, u16 block, void* addr, void* spare); +s32 osBbCardEraseBlock(u32 dev, u16 block); +s32 osBbCardWriteBlock(u32 dev, u16 block, void* addr, void* spare); +s32 osBbCardStatus(u32 dev, u8* status); +s32 osBbCardChange(void); +s32 osBbCardClearChange(void); +u32 osBbCardBlocks(u32 dev); +s32 osBbCardUnhappy(void); + +/* private */ + +s32 __osBbCardGetAccess(void); +void __osBbCardRelAccess(void); +s32 __osBbCardWaitEvent(void); +s32 __osBbCardFlushEvent(void); +s32 __osBbCardPresent(void); + +extern u16 __osBbCardBlocks; +extern u8 __osBbCardChange; +extern u8 __osBbCardInit; +extern u8 __osBbCardMultiplane; + +#endif diff --git a/include/PR/bbfs.h b/include/PR/bbfs.h index b470326b..77986fc4 100644 --- a/include/PR/bbfs.h +++ b/include/PR/bbfs.h @@ -1,10 +1,10 @@ -#ifndef BBFS_H_ -#define BBFS_H_ +#ifndef _BBFS_H_ +#define _BBFS_H_ #include "ultratypes.h" #define BB_FL_BLOCK_SIZE 16384 -#define BB_INODE16_NAMELEN 11 /* maximum name length */ +#define BB_INODE16_NAMELEN 11 /* maximum name length */ #define BB_INODE16_NUM 409 #define BBFS_ERR_NO_CARD (-1) /* card not present */ @@ -17,19 +17,37 @@ #define BBFS_ERR_ENTRY (-8) /* no entry */ /* Used for saving auxilliary game state data */ -#define BBFS_ERR_STATE (-9) /* invalid state */ -#define BBFS_ERR_STATE_LIMIT (-10) /* state limit reached */ +#define BBFS_ERR_STATE (-9) /* invalid state */ +#define BBFS_ERR_STATE_LIMIT (-10) /* state limit reached */ typedef u16 BbFatEntry; +#define BBFS_BLOCK_FREE (0x0000) /* block is available */ +#define BBFS_BLOCK_EOC (0xFFFF) /* indicates end-of-chain */ +#define BBFS_BLOCK_BAD (0xFFFE) /* indicates a bad block */ +#define BBFS_BLOCK_RESERVED (0xFFFD) /* indicates system-reserved area */ + +/** + * FS structure assuming 64MB NAND with 4096 blocks: + * - 0 .. 63 SKSA + * - 64 .. 4079 Data area + * - 4080 .. 4095 BBFS FAT + */ +#define BBFS_SKSA_LIMIT 64 /* FIRST 64 blocks */ +#define BBFS_FAT_LIMIT 16 /* LAST 16 blocks */ typedef struct { - /* 0x0000 */ u8 name[BB_INODE16_NAMELEN]; + /* 0x0000 */ u8 name[BB_INODE16_NAMELEN]; // 8.3 name+extension format /* 0x000B */ u8 type; - /* 0x000C */ u16 block; + /* 0x000C */ u16 block; // first block in the chain belonging to this file /* 0x000E */ u16 pad; /* 0x0010 */ u32 size; } BbInode; // size = 0x14 +// `fat` is a `BbFat16` pointer +#define BBFS_NEXT_BLOCK(fat, b) ((fat)[(b) >> 0xC].entry[(b) & 0xFFF]) + +#define BBFS_CHECKSUM_VALUE (0xCAD7) + typedef struct { /* 0x0000 */ BbFatEntry entry[4096]; /* 0x2000 */ BbInode inode[BB_INODE16_NUM]; @@ -39,9 +57,6 @@ typedef struct { /* 0x3FFE */ u16 cksum; } BbFat16; // size = 0x4000 -// `fat` is a `BbFat16` pointer -#define BBFS_NEXT_BLOCK(fat, b) (fat[b >> 0xC].entry[b & 0xFFF]) - extern BbFat16* __osBbFat; typedef struct { diff --git a/include/PR/bbnand.h b/include/PR/bbnand.h new file mode 100644 index 00000000..0bb7ae86 --- /dev/null +++ b/include/PR/bbnand.h @@ -0,0 +1,127 @@ +#ifndef _BBNAND_H_ +#define _BBNAND_H_ + +#define NAND_BYTES_PER_PAGE 0x200 +#define NAND_PAGE_SPARE_SIZE 0x10 +#define NAND_PAGES_PER_BLOCK 32 +#define NAND_BYTES_PER_BLOCK (NAND_PAGES_PER_BLOCK * NAND_BYTES_PER_PAGE) + +#define NAND_BLOCK_TO_PAGE(blockNum) ((blockNum) * NAND_PAGES_PER_BLOCK) +#define NAND_PAGE_TO_ADDR(pageNum) ((pageNum) * NAND_BYTES_PER_PAGE) +#define NAND_BLOCK_TO_ADDR(pageNum) ((pageNum) * NAND_BYTES_PER_BLOCK) + +/* NAND Control (Read) */ +#define NAND_STATUS_BUSY (1 << 31) +#define NAND_STATUS_ERROR_DB (1 << 10) /* Double-bit error, uncorrectable */ +#define NAND_STATUS_ERROR_SB (1 << 11) /* Single-bit error, automatically corrected by ECC if enabled */ + +/* NAND Control (Write) */ +/* Write 0 to PI_48_REG to clear flash interrupt */ +#define NAND_CTRL_CLR_INTR 0 +/* Other write bits */ +#define NAND_CTRL_EXEC (1 << 31) /* Execute NAND command immediately after write */ +#define NAND_CTRL_INTR (1 << 30) /* Interrupt when done */ +#define NAND_CTRL_UNK29 (1 << 29) +#define NAND_CTRL_UNK28 (1 << 28) +#define NAND_CTRL_UNK27 (1 << 27) +#define NAND_CTRL_UNK26 (1 << 26) +#define NAND_CTRL_UNK25 (1 << 25) +#define NAND_CTRL_UNK24 (1 << 24) +#define NAND_CTRL_CMD(cmd) ((cmd) << 16) /* NAND command, sent directly to the NAND chip */ +#define NAND_CTRL_UNK15 (1 << 15) +#define NAND_CTRL_BUFSEL(n) ((n) << 14) /* PI Buffer select, offset 0x000 or 0x200 */ +#define NAND_CTRL_DEVICE(n) ((n) << 12) /* NAND device select (2-bit) */ +#define NAND_CTRL_ECC (1 << 11) /* 1 if do ECC */ +#define NAND_CTRL_MULTICYCLE (1 << 10) /* 1 if NAND command is multicycle */ +#define NAND_CTRL_XFER_LEN(n) ((n) << 0) /* Transfer length in bytes between NAND and PI Buffer (10-bit) */ + +/* NAND Command IDs */ +#define NAND_CMD_READ_0 0x00 +#define NAND_CMD_READ_1 0x01 +#define NAND_CMD_READ_2 0x50 +#define NAND_CMD_READ_ID 0x90 +#define NAND_CMD_RESET 0xFF +#define NAND_CMD_FILL_PAGE 0x80 +#define NAND_CMD_WRITE_PAGE 0x10 +#define NAND_CMD_DUMMY_PAGE 0x11 +#define NAND_CMD_DUMMY_READ 0x03 +#define NAND_CMD_COPY_BACK 0x8A +#define NAND_CMD_ERASE_PAGE 0x60 +#define NAND_CMD_EXEC_ERASE 0xD0 +#define NAND_CMD_READ_STATUS 0x70 +#define NAND_CMD_READ_STATUS_MP 0x71 + +/* NAND Read Status (RSTAT) */ + +#define NAND_RSTAT_ERASE_OK 0xC0 + +/* NAND Read ID Response */ + +#define NAND_ID_MULTIPLANE 0xC0 + +#define NAND_ID_GET_MFG(status) (((status) >> 0x18) & 0xFF) +#define NAND_ID_GET_TYPE(status) (((status) >> 0x10) & 0xFF) +#define NAND_ID_IS_MULTIPLANE(status) ((((status) >> 0x00) & 0xFF) == NAND_ID_MULTIPLANE) + +/* NAND Command Macros */ + +#define NAND_READ_0(nBytes, bufSelect, device, doEcc, intrDone) \ + (NAND_CTRL_EXEC | ((intrDone) ? NAND_CTRL_INTR : 0) | \ + NAND_CTRL_UNK28 | NAND_CTRL_UNK27 | NAND_CTRL_UNK26 | NAND_CTRL_UNK25 | NAND_CTRL_UNK24 | \ + NAND_CTRL_CMD(NAND_CMD_READ_0) | \ + NAND_CTRL_UNK15 | NAND_CTRL_BUFSEL(bufSelect) | NAND_CTRL_DEVICE(device) | \ + ((doEcc) ? NAND_CTRL_ECC : 0) | NAND_CTRL_XFER_LEN(nBytes)) + +#define NAND_ERASE_PAGE(device, intrDone) \ + (NAND_CTRL_EXEC | ((intrDone) ? NAND_CTRL_INTR : 0) | \ + NAND_CTRL_UNK27 | NAND_CTRL_UNK26 | NAND_CTRL_UNK25 | \ + NAND_CTRL_CMD(NAND_CMD_ERASE_PAGE) | \ + NAND_CTRL_DEVICE(device) | NAND_CTRL_MULTICYCLE) + +#define NAND_EXEC_ERASE(device, intrDone) \ + (NAND_CTRL_EXEC | ((intrDone) ? NAND_CTRL_INTR : 0) | \ + NAND_CTRL_CMD(NAND_CMD_EXEC_ERASE) | \ + NAND_CTRL_UNK15 | NAND_CTRL_DEVICE(device)) + +#define NAND_READ_ID(bufSelect, device, intrDone) \ + (NAND_CTRL_EXEC | ((intrDone) ? NAND_CTRL_INTR : 0) | \ + NAND_CTRL_UNK28 | NAND_CTRL_UNK24 | \ + NAND_CTRL_CMD(NAND_CMD_READ_ID) | \ + NAND_CTRL_DEVICE(device) | \ + NAND_CTRL_XFER_LEN(4)) + +#define NAND_READ_STATUS(bufSelect, device, intrDone) \ + (NAND_CTRL_EXEC | ((intrDone) ? NAND_CTRL_INTR : 0) | \ + NAND_CTRL_UNK28 | \ + NAND_CTRL_CMD(NAND_CMD_READ_STATUS) | \ + NAND_CTRL_BUFSEL(bufSelect) | NAND_CTRL_DEVICE(device) | \ + NAND_CTRL_XFER_LEN(1)) + +#define NAND_READ_STATUS_CMD(cmd, bufSelect, device, intrDone) \ + (NAND_CTRL_EXEC | ((intrDone) ? NAND_CTRL_INTR : 0) | \ + NAND_CTRL_UNK28 | \ + NAND_CTRL_CMD(cmd) | \ + NAND_CTRL_BUFSEL(bufSelect) | NAND_CTRL_DEVICE(device) | \ + NAND_CTRL_XFER_LEN(1)) + +#define NAND_FILL_PAGE(nBytes, bufSelect, device, doEcc, intrDone) \ + (NAND_CTRL_EXEC | ((intrDone) ? NAND_CTRL_INTR : 0) | \ + NAND_CTRL_UNK29 | NAND_CTRL_UNK27 | NAND_CTRL_UNK26 | NAND_CTRL_UNK25 | NAND_CTRL_UNK24 | \ + NAND_CTRL_CMD(NAND_CMD_FILL_PAGE) | \ + NAND_CTRL_BUFSEL(bufSelect) | NAND_CTRL_DEVICE(device) | \ + ((doEcc) ? NAND_CTRL_ECC : 0) | NAND_CTRL_MULTICYCLE | NAND_CTRL_XFER_LEN(nBytes)) + +#define NAND_WRITE_PAGE(device, intrDone) \ + (NAND_CTRL_EXEC | ((intrDone) ? NAND_CTRL_INTR : 0) | \ + NAND_CTRL_CMD(NAND_CMD_WRITE_PAGE) | \ + NAND_CTRL_UNK15 | NAND_CTRL_DEVICE(device)) + +#define NAND_DUMMY_PAGE(device, intrDone) \ + (NAND_CTRL_EXEC | ((intrDone) ? NAND_CTRL_INTR : 0) | \ + NAND_CTRL_CMD(NAND_CMD_DUMMY_PAGE) | \ + NAND_CTRL_UNK15 | NAND_CTRL_DEVICE(device)) + +/* Configuration with which to program PI_48_REG with when using ATB. */ +#define NAND_ATB_CONFIG(device, doEcc) (NAND_READ_0(0x3FF, 0, device, doEcc, FALSE) & ~NAND_CTRL_EXEC) + +#endif diff --git a/include/PR/bcp.h b/include/PR/bcp.h index 59367442..78c3ec67 100644 --- a/include/PR/bcp.h +++ b/include/PR/bcp.h @@ -22,7 +22,6 @@ #define MI_38_REG (MI_BASE_REG + 0x38) - //! MI_HW_INTR_MASK_REG ? #define MI_3C_REG (MI_BASE_REG + 0x3C) @@ -42,7 +41,18 @@ -//! PI_CARD_CNT_REG ? +/** + * [31] : Exec + * [30] : Raise interrupt when command is done + * [29:24] : ?? + * [23:16] : NAND command + * [15] : ?? + * [14] : Buffer Select + * [13:12] : Device Select + * [11] : ECC + * [10] : NAND command is multi-cycle + * [ 9: 0] : Transfer Length + */ #define PI_48_REG (PI_BASE_REG + 0x48) @@ -88,8 +98,9 @@ //! PI_EX_DMA_BUF ? -#define PI_10000_REG(i) (PI_BASE_REG + 0x10000 + (i)) - +#define PI_10000_BUF(offset) (PI_BASE_REG + 0x10000 + (offset)) +#define PI_NAND_DATA_BUFFER(bufSelect, offset) PI_10000_BUF((bufSelect) * 0x200 + (offset)) +#define PI_NAND_SPARE_BUFFER(bufSelect, offset) PI_10000_BUF(0x400 + (bufSelect) * 0x10 + (offset)) //! PI_ATB_LOWER_REG ? diff --git a/src/bb/card/carderase.c b/src/bb/card/carderase.c index 1ea65671..76a2412b 100644 --- a/src/bb/card/carderase.c +++ b/src/bb/card/carderase.c @@ -1,4 +1,5 @@ #include "PR/os_internal.h" +#include "PR/bbcard.h" #include "bcp.h" void __osBbCardRelAccess(void); @@ -9,31 +10,31 @@ s32 __osBbCardStatus(u32 dev, u8* status, u32 buf); extern u8 __osBbCardMultiplane; static void erase_block(u32 dev, u32 addr) { - IO_WRITE(PI_70_REG, addr << 0xE); - IO_WRITE(PI_48_REG, (dev << 0xC) | 0x8E600400); + IO_WRITE(PI_70_REG, NAND_BLOCK_TO_ADDR(addr)); + IO_WRITE(PI_48_REG, NAND_ERASE_PAGE(dev, FALSE)); do { if (IO_READ(MI_38_REG) & 0x02000000) { return; } - } while (IO_READ(PI_48_REG) & 0x80000000); + } while (IO_READ(PI_48_REG) & NAND_STATUS_BUSY); - IO_WRITE(PI_48_REG, (dev << 0xC) | 0xC0D08000); + IO_WRITE(PI_48_REG, NAND_EXEC_ERASE(dev, TRUE)); } static void erase_blocks(u32 dev, u16* addr, u32 n) { do { - IO_WRITE(PI_70_REG, addr[--n] << 0xE); - IO_WRITE(PI_48_REG, (dev << 0xC) | 0x8E600400); + IO_WRITE(PI_70_REG, NAND_BLOCK_TO_ADDR(addr[--n])); + IO_WRITE(PI_48_REG, NAND_ERASE_PAGE(dev, FALSE)); do { if (IO_READ(MI_38_REG) & 0x02000000) { return; } - } while (IO_READ(PI_48_REG) & 0x80000000); + } while (IO_READ(PI_48_REG) & NAND_STATUS_BUSY); } while (n != 0); - IO_WRITE(PI_48_REG, (dev << 0xC) | 0xC0D08000); + IO_WRITE(PI_48_REG, NAND_EXEC_ERASE(dev, TRUE)); } s32 osBbCardEraseBlock(u32 dev, u16 block) { @@ -47,10 +48,10 @@ s32 osBbCardEraseBlock(u32 dev, u16 block) { erase_block(dev, block); rv = __osBbCardWaitEvent(); - if ((rv < 0) || __osBbCardStatus(dev, &tmp, 0) != 0) { - rv = -4; - } else if (tmp != 0xC0) { - rv = -2; + if (rv < 0 || __osBbCardStatus(dev, &tmp, 0) != 0) { + rv = BBCARD_ERR_CHANGED; + } else if (tmp != NAND_RSTAT_ERASE_OK) { + rv = BBCARD_ERR_FAIL; } __osBbCardRelAccess(); return rv; @@ -91,9 +92,9 @@ s32 osBbCardEraseBlocks(u32 dev, u16* block, u32 n) { } if (__osBbCardStatus(dev, &tmp, 0) != 0) { - rv = -4; - } else if (tmp != 0xC0) { - rv = -2; + rv = BBCARD_ERR_CHANGED; + } else if (tmp != NAND_RSTAT_ERASE_OK) { + rv = BBCARD_ERR_FAIL; } err: __osBbCardRelAccess(); diff --git a/src/bb/card/cardid.c b/src/bb/card/cardid.c index d156dae7..cf532c7e 100644 --- a/src/bb/card/cardid.c +++ b/src/bb/card/cardid.c @@ -1,12 +1,6 @@ #include "PR/os_internal.h" #include "PR/bcp.h" - -s32 __osBbCardGetAccess(void); -void __osBbCardRelAccess(void); - -s32 __osBbCardWaitEvent(void); - -extern s8 __osBbCardMultiplane; +#include "PR/bbcard.h" s32 osBbCardReadId(u32 dev, u32* mfg, u32* type) { u32 status; @@ -18,13 +12,13 @@ s32 osBbCardReadId(u32 dev, u32* mfg, u32* type) { } IO_WRITE(PI_70_REG, 0); - IO_WRITE(PI_48_REG, (dev << 12) | 0xD1900004); + IO_WRITE(PI_48_REG, NAND_READ_ID(0, dev, TRUE)); rv = __osBbCardWaitEvent(); - status = IO_READ(PI_10000_REG(0)); - *mfg = status >> 0x18; - *type = (status >> 0x10) & 0xFF; - __osBbCardMultiplane = (status & 0xFF) == 0xC0; + status = IO_READ(PI_NAND_DATA_BUFFER(0, 0)); + *mfg = NAND_ID_GET_MFG(status); + *type = NAND_ID_GET_TYPE(status); + __osBbCardMultiplane = NAND_ID_IS_MULTIPLANE(status); __osBbCardRelAccess(); return rv; diff --git a/src/bb/card/cardinit.c b/src/bb/card/cardinit.c index 484e4cc9..a1647f93 100644 --- a/src/bb/card/cardinit.c +++ b/src/bb/card/cardinit.c @@ -1,4 +1,5 @@ #include "PR/os_internal.h" +#include "PR/bbcard.h" #include "PR/bcp.h" u8 __osBbCardChange = TRUE; @@ -51,9 +52,9 @@ s32 __osBbCardGetAccess(void) { __osBbCardRelAccess(); if (!__osBbCardPresent()) { - return -1; + return BBCARD_ERR_NO_CARD; } - return -4; + return BBCARD_ERR_CHANGED; } return 0; } @@ -67,7 +68,7 @@ void osBbCardInit(void) { osSendMesg(&__osBbCardAccessQueue, NULL, 0); __osBbCardInitEvent(); - IO_WRITE(MI_3C_REG, 0x08002000); + IO_WRITE(MI_3C_REG, 0x08002000); // enable flash interrupt __osBbCardHandler.type = 6; __osBbCardHandler.baseAddress = 0; @@ -84,7 +85,7 @@ void osBbCardInit(void) { __osBbCardInit = TRUE; } - IO_WRITE(PI_48_REG, 0); + IO_WRITE(PI_48_REG, NAND_CTRL_CLR_INTR); __osBbCardChange = FALSE; __osBbCardFlushEvent(); @@ -113,15 +114,15 @@ void __osBbCardDmaCopy(u32 which, void* addr, u32 dir) { m.hdr.pri = 0; m.hdr.retQueue = &__osBbCardDmaQ; m.dramAddr = addr; - m.size = 0x200; - m.devAddr = which * 0x200; + m.size = NAND_BYTES_PER_PAGE; + m.devAddr = which * NAND_BYTES_PER_PAGE; if (dir == OS_WRITE) { - osWritebackDCache(addr, 0x200); + osWritebackDCache(addr, NAND_BYTES_PER_PAGE); } osEPiStartDma(&__osBbCardHandler, &m, dir); osRecvMesg(&__osBbCardDmaQ, NULL, OS_MESG_BLOCK); if (dir == OS_READ) { - osInvalDCache(addr, 0x200); + osInvalDCache(addr, NAND_BYTES_PER_PAGE); } } diff --git a/src/bb/card/cardmgr.c b/src/bb/card/cardmgr.c index 049e75e2..2bad3c0f 100644 --- a/src/bb/card/cardmgr.c +++ b/src/bb/card/cardmgr.c @@ -1,4 +1,5 @@ #include "PR/os_internal.h" +#include "PR/bbcard.h" #include "macros.h" #ident "$Revision: 1.1 $" @@ -51,8 +52,8 @@ s32 __osBbCardWaitEvent(void) { osSyncPrintf("md interrupt\n"); #endif __osBbCardChange = TRUE; - return -4; + return BBCARD_ERR_CHANGED; default: - return -2; + return BBCARD_ERR_FAIL; } } diff --git a/src/bb/card/cardprobe.c b/src/bb/card/cardprobe.c index c2895048..27cdc4ca 100644 --- a/src/bb/card/cardprobe.c +++ b/src/bb/card/cardprobe.c @@ -1,11 +1,8 @@ #include "PR/os_internal.h" #include "PR/bcp.h" +#include "PR/bbcard.h" -s32 __osBbCardFlushEvent(void); -s32 __osBbCardGetAccess(void); -void __osBbCardRelAccess(void); void __osBbDelay(u32); -extern u8 __osBbCardChange; s32 osBbCardProbe(u32 dev) { s32 count; @@ -19,14 +16,14 @@ s32 osBbCardProbe(u32 dev) { return rv; } - IO_WRITE(PI_10000_REG(0), 0); - IO_WRITE(PI_48_REG, (dev << 0xC) | 0x90700001); + IO_WRITE(PI_NAND_DATA_BUFFER(0, 0), 0); + IO_WRITE(PI_48_REG, NAND_READ_STATUS(0, dev, FALSE)); - rv = -1; + rv = BBCARD_ERR_NO_CARD; for (count = 0; count < 1000; count++) { - if (!(IO_READ(PI_48_REG) & 0x80000000)) { - if ((IO_READ(PI_10000_REG(0)) >> 0x18) == 0xC0) { + if (!(IO_READ(PI_48_REG) & NAND_STATUS_BUSY)) { + if ((IO_READ(PI_NAND_DATA_BUFFER(0, 0)) >> 0x18) == 0xC0) { rv = 0; #ifdef _DEBUG @@ -39,7 +36,7 @@ s32 osBbCardProbe(u32 dev) { } __osBbDelay(10); } - IO_WRITE(PI_48_REG, 0); + IO_WRITE(PI_48_REG, NAND_CTRL_CLR_INTR); __osBbCardChange = save; #ifdef _DEBUG osSyncPrintf("probe fails\n"); diff --git a/src/bb/card/cardread.c b/src/bb/card/cardread.c index 20898dc5..a8385007 100644 --- a/src/bb/card/cardread.c +++ b/src/bb/card/cardread.c @@ -1,4 +1,5 @@ #include "PR/os_internal.h" +#include "PR/bbcard.h" #include "bcp.h" void __osBbCardDmaCopy(u32 which, void* addr, u32 dir); @@ -9,8 +10,8 @@ s32 __osBbCardWaitEvent(void); u32 __osBbCardSbErr; static void read_page(u32 dev, u32 addr, u32 which_buf) { - IO_WRITE(PI_70_REG, addr << 9); - IO_WRITE(PI_48_REG, 0xDF008000 | (which_buf << 0xE) | (dev << 0xC) | 0xA10); + IO_WRITE(PI_70_REG, NAND_PAGE_TO_ADDR(addr)); + IO_WRITE(PI_48_REG, NAND_READ_0(0x210, which_buf, dev, TRUE, TRUE)); } s32 osBbCardReadBlock(u32 dev, u16 block, void* addr, void* spare) { @@ -29,14 +30,14 @@ s32 osBbCardReadBlock(u32 dev, u16 block, void* addr, void* spare) { ((u8*)spare)[5] = 0xFF; } - for (i = 0; i < 0x20; i++) { - read_page(dev, (block * 0x4000 + i * 0x200) >> 9, b); + for (i = 0; i < NAND_PAGES_PER_BLOCK; i++) { + read_page(dev, (block * NAND_BYTES_PER_BLOCK + i * NAND_BYTES_PER_PAGE) / NAND_BYTES_PER_PAGE, b); if (i != 0) { - __osBbCardDmaCopy(b ^ 1, &((u8*)addr)[0x200 * (i - 1)], 0); + __osBbCardDmaCopy(b ^ 1, &((u8*)addr)[NAND_BYTES_PER_PAGE * (i - 1)], 0); if (spare != NULL) { - u32 addr = PI_BASE_REG + 0x10400 + (b ^ 1) * 0x10; + u32 addr = PI_NAND_SPARE_BUFFER(b ^ 1, 0); ((u8*)spare)[5] &= IO_READ(addr + 4) >> 8; } @@ -48,29 +49,29 @@ s32 osBbCardReadBlock(u32 dev, u16 block, void* addr, void* spare) { } x = IO_READ(PI_48_REG); - if (x & 0x400) { - db = -2; + if (x & NAND_STATUS_ERROR_DB) { + db = BBCARD_ERR_FAIL; - if (spare == NULL || i == 0x1F) { + if (spare == NULL || i == (NAND_PAGES_PER_BLOCK - 1)) { goto err; } } - if (x & 0x800) { + if (x & NAND_STATUS_ERROR_SB) { __osBbCardSbErr++; } b ^= 1; } - __osBbCardDmaCopy(b ^ 1, addr + 0x200 * (i - 1), 0); + __osBbCardDmaCopy(b ^ 1, addr + NAND_BYTES_PER_PAGE * (i - 1), 0); err: if (spare != NULL) { u8* p = spare; - u32 addr = PI_BASE_REG + 0x10400 + (b ^ 1) * 0x10; + u32 addr = PI_NAND_SPARE_BUFFER(b ^ 1, 0); - for (i = 0; i < 4; i++) { - u32 x = IO_READ(addr + 4 * i); + for (i = 0; i < NAND_PAGE_SPARE_SIZE/sizeof(u32); i++) { + u32 x = IO_READ(addr + sizeof(u32) * i); p[0] = x >> 0x18; p[1] = x >> 0x10; @@ -81,7 +82,7 @@ s32 osBbCardReadBlock(u32 dev, u16 block, void* addr, void* spare) { } p[3] = x; - p += 4; + p += sizeof(u32); } } diff --git a/src/bb/card/cardstatus.c b/src/bb/card/cardstatus.c index f3f0a2cb..9ccbcd80 100644 --- a/src/bb/card/cardstatus.c +++ b/src/bb/card/cardstatus.c @@ -1,24 +1,13 @@ #include "PR/os_internal.h" #include "PR/bcp.h" - -s32 __osBbCardWaitEvent(void); - -s32 __osBbCardGetAccess(void); -void __osBbCardRelAccess(void); - -s32 __osBbCardPresent(void); - -extern u16 __osBbCardBlocks; -extern u8 __osBbCardChange; -extern u8 __osBbCardInit; -extern u8 __osBbCardMultiplane; +#include "PR/bbcard.h" s32 osBbCardUnhappy(void) { if (!__osBbCardInit || !__osBbCardPresent()) { - return -1; + return BBCARD_ERR_NO_CARD; } if (__osBbCardChange) { - return -4; + return BBCARD_ERR_CHANGED; } return 0; } @@ -27,13 +16,12 @@ s32 __osBbCardStatus(u32 dev, u8* status, u32 buf) { s32 rv; u32 cmd; - cmd = __osBbCardMultiplane ? 0x71 : 0x70; - - IO_WRITE(PI_48_REG, 0xD0000000 | (cmd << 0x10) | (buf << 0xE) | (dev << 0xC) | 1); + cmd = __osBbCardMultiplane ? NAND_CMD_READ_STATUS_MP : NAND_CMD_READ_STATUS; + IO_WRITE(PI_48_REG, NAND_READ_STATUS_CMD(cmd, buf, dev, TRUE)); rv = __osBbCardWaitEvent(); if (rv == 0) { - *status = IO_READ(PI_10000_REG((buf != 0) ? 0x200 : 0x000)) >> 0x18; + *status = IO_READ(PI_NAND_DATA_BUFFER(buf != 0, 0)) >> 0x18; } else { *status = 0; } diff --git a/src/bb/card/cardwrite.c b/src/bb/card/cardwrite.c index c0fe0aa8..2a091f76 100644 --- a/src/bb/card/cardwrite.c +++ b/src/bb/card/cardwrite.c @@ -1,4 +1,5 @@ #include "PR/os_internal.h" +#include "PR/bbcard.h" #include "bcp.h" void __osBbCardDmaCopy(u32 which, void* addr, u32 dir); @@ -14,13 +15,13 @@ u8 __osBbCardNoEcc; #endif static void fill_page(unsigned int dev, unsigned int addr, int which_buf, int wait) { - IO_WRITE(PI_70_REG, addr << 9); + IO_WRITE(PI_70_REG, NAND_PAGE_TO_ADDR(addr)); #ifndef _DEBUG - IO_WRITE(PI_48_REG, 0xAF800000 | (which_buf << 0xE) | (dev << 0xC) | 0xE10); + IO_WRITE(PI_48_REG, NAND_FILL_PAGE(0x210, which_buf, dev, TRUE, FALSE)); #else - IO_WRITE(PI_48_REG, 0xAF800000 | (which_buf << 0xE) | (dev << 0xC) | (((addr & 0x1F) == 0x1F && __osBbCardNoEcc) ? 0 : 0x800) | 0x610); - if ((__osBbCardNoEcc != 0) && (addr & 0x1F) == 0x1F) { + IO_WRITE(PI_48_REG, NAND_FILL_PAGE(0x210, which_buf, dev, !((addr & 0x1F) == 0x1F && __osBbCardNoEcc), FALSE)); + if (__osBbCardNoEcc != 0 && (addr & 0x1F) == 0x1F) { osSyncPrintf("write no ecc\n"); } #endif @@ -30,28 +31,28 @@ static void fill_page(unsigned int dev, unsigned int addr, int which_buf, int wa if (IO_READ(MI_38_REG) & 0x02000000) { return; } - } while (IO_READ(PI_48_REG) & 0x80000000); + } while (IO_READ(PI_48_REG) & NAND_STATUS_BUSY); } } static void write_page(unsigned int dev) { - IO_WRITE(PI_48_REG, 0xC0108000 | (dev << 0xC)); + IO_WRITE(PI_48_REG, NAND_WRITE_PAGE(dev, TRUE)); do { if (IO_READ(MI_38_REG) & 0x02000000) { return; } - } while (IO_READ(PI_48_REG) & 0x80000000); + } while (IO_READ(PI_48_REG) & NAND_STATUS_BUSY); } static void write_dummy(u32 dev) { - IO_WRITE(PI_48_REG, 0x80118000 | (dev << 0xC)); + IO_WRITE(PI_48_REG, NAND_DUMMY_PAGE(dev, FALSE)); do { if (IO_READ(MI_38_REG) & 0x02000000) { return; } - } while (IO_READ(PI_48_REG) & 0x80000000); + } while (IO_READ(PI_48_REG) & NAND_STATUS_BUSY); } s32 osBbCardWriteBlock(u32 dev, u16 block, void* addr, void* spare) { @@ -62,7 +63,7 @@ s32 osBbCardWriteBlock(u32 dev, u16 block, void* addr, void* spare) { #ifdef _DEBUG if (((u32)addr & 0xF) != 0) { - return -3; + return BBCARD_ERR_INVALID; } #endif @@ -74,30 +75,30 @@ s32 osBbCardWriteBlock(u32 dev, u16 block, void* addr, void* spare) { if (spare != NULL) { u8* var_t1 = spare; - for (i = 0; i < 0x10; i += 4) { + for (i = 0; i < NAND_PAGE_SPARE_SIZE; i += sizeof(u32)) { u32 x = (var_t1[0] << 0x18) | (var_t1[1] << 0x10) | (var_t1[2] << 8) | var_t1[3]; - IO_WRITE(PI_BASE_REG + 0x10400 + i, x); - IO_WRITE(PI_BASE_REG + 0x10410 + i, x); + IO_WRITE(PI_NAND_SPARE_BUFFER(0, i), x); + IO_WRITE(PI_NAND_SPARE_BUFFER(1, i), x); var_t1 += 4; } } else { - for (i = 0; i < 0x10; i += 4) { - IO_WRITE(PI_BASE_REG + 0x10400 + i, 0xFFFFFFFF); - IO_WRITE(PI_BASE_REG + 0x10410 + i, 0xFFFFFFFF); + for (i = 0; i < NAND_PAGE_SPARE_SIZE; i += sizeof(u32)) { + IO_WRITE(PI_NAND_SPARE_BUFFER(0, i), 0xFFFFFFFF); + IO_WRITE(PI_NAND_SPARE_BUFFER(1, i), 0xFFFFFFFF); } } __osBbCardDmaCopy(b, addr, 1); - for (i = 0; i < 0x20; i++) { - fill_page(dev, (block * 0x4000 + i * 0x200) >> 9, b, 1); + for (i = 0; i < NAND_PAGES_PER_BLOCK; i++) { + fill_page(dev, (block * NAND_BYTES_PER_BLOCK + i * NAND_BYTES_PER_PAGE) / NAND_BYTES_PER_PAGE, b, 1); write_page(dev); if (i < 0x1F) { - __osBbCardDmaCopy(b ^ 1, &((u8*)addr)[0x200 * (i + 1)], 1); + __osBbCardDmaCopy(b ^ 1, &((u8*)addr)[NAND_BYTES_PER_PAGE * (i + 1)], 1); } rv = __osBbCardWaitEvent(); @@ -108,7 +109,7 @@ s32 osBbCardWriteBlock(u32 dev, u16 block, void* addr, void* spare) { #ifdef _DEBUG osSyncPrintf("block %d write failed 0x%x\n", block, tmp); #endif - rv = -2; + rv = BBCARD_ERR_FAIL; goto err; } b ^= 1; @@ -140,16 +141,16 @@ s32 osBbCardWriteBlocks(u32 dev, u16* block, u32 n, void* addr, void* spare) { if (spare != NULL) { u8* p = spare; - for (i = 0; i < 0x10; i += 4) { + for (i = 0; i < NAND_PAGE_SPARE_SIZE; i += sizeof(u32)) { u32 x = (p[0] << 0x18) | (p[1] << 0x10) | (p[2] << 8) | p[3]; - IO_WRITE(PI_BASE_REG + 0x10400 + i, x); - IO_WRITE(PI_BASE_REG + 0x10410 + i, x); - p += 4; + IO_WRITE(PI_NAND_SPARE_BUFFER(0, i), x); + IO_WRITE(PI_NAND_SPARE_BUFFER(1, i), x); + p += sizeof(u32); } } else { - for (i = 0; i < 0x10; i += 4) { - IO_WRITE(PI_BASE_REG + 0x10400 + i, 0xFFFFFFFF); - IO_WRITE(PI_BASE_REG + 0x10410 + i, 0xFFFFFFFF); + for (i = 0; i < NAND_PAGE_SPARE_SIZE; i += sizeof(u32)) { + IO_WRITE(PI_NAND_SPARE_BUFFER(0, i), 0xFFFFFFFF); + IO_WRITE(PI_NAND_SPARE_BUFFER(1, i), 0xFFFFFFFF); } } @@ -168,20 +169,20 @@ s32 osBbCardWriteBlocks(u32 dev, u16* block, u32 n, void* addr, void* spare) { k++; } - for (i = 0; i < 0x20; i++) { - __osBbCardDmaCopy(b, addr + j * 0x4000 + i * 0x200, 1); + for (i = 0; i < NAND_PAGES_PER_BLOCK; i++) { + __osBbCardDmaCopy(b, (u8*)addr + j * NAND_BYTES_PER_BLOCK + i * NAND_BYTES_PER_PAGE, 1); for(l = j; l < k; l++) { - fill_page(dev, ((block[l] * 0x4000) + (i * 0x200)) >> 9, (s32) b, 0); + fill_page(dev, (block[l] * NAND_BYTES_PER_BLOCK + i * NAND_BYTES_PER_PAGE) / NAND_BYTES_PER_PAGE, (s32)b, 0); if (l < k - 1) { - __osBbCardDmaCopy(b ^ 1, addr + ((l + 1) * 0x4000) + (i * 0x200), 1); + __osBbCardDmaCopy(b ^ 1, (u8*)addr + (l + 1) * NAND_BYTES_PER_BLOCK + i * NAND_BYTES_PER_PAGE, 1); } do { if (IO_READ(MI_38_REG) & 0x02000000) { break; } - } while (IO_READ(PI_48_REG) & 0x80000000); + } while (IO_READ(PI_48_REG) & NAND_STATUS_BUSY); if (l == k - 1) { write_page(dev); @@ -197,11 +198,11 @@ s32 osBbCardWriteBlocks(u32 dev, u16* block, u32 n, void* addr, void* spare) { } if (__osBbCardStatus(dev, &tmp, 0) != 0) { - rv = -4; + rv = BBCARD_ERR_CHANGED; goto err; } if (tmp != 0xC0) { - rv = -2; + rv = BBCARD_ERR_FAIL; goto err; } } diff --git a/src/bb/fs/fscreate.c b/src/bb/fs/fscreate.c new file mode 100644 index 00000000..d96719f2 --- /dev/null +++ b/src/bb/fs/fscreate.c @@ -0,0 +1,144 @@ +#include "PR/os_internal.h" +#include "PR/bbcard.h" +#include "PR/bbfs.h" + +void __osBbFsFormatName(char* fname, const char* name) { + int i; + int j; + + for (i = 0; name[i] != '\0' && name[i] != '.' && i < 8; i++) { + fname[i] = name[i]; + } + + for (j = i; j < 8; j++) { + fname[j] = '\0'; + } + + if (name[i] == '.') { + i++; + + while (name[i] != '\0') { + if (j >= BB_INODE16_NAMELEN) { + return; + } + fname[j++] = name[i++]; + } + } + + while (j < BB_INODE16_NAMELEN) { + fname[j++] = '\0'; + } +} + +s32 osBbFCreate(const char* name, u8 type, u32 len) { + u16 i; + u16 b; + u16 prev = BBFS_BLOCK_FREE; + BbInode* in = NULL; + BbFat16* fat; + s32 rv; + s32 incr; + char fname[BB_INODE16_NAMELEN]; + + if (len % BB_FL_BLOCK_SIZE != 0) { + return BBFS_ERR_INVALID; + } + + __osBbFsFormatName(fname, name); + if (fname[0] == '\0') { + return BBFS_ERR_INVALID; + } + + rv = __osBbFsGetAccess(); + if (rv < 0) { + return rv; + } + + rv = BBFS_ERR_EXISTS; + fat = __osBbFat; + + for (i = 0; i < BB_INODE16_NUM; i++) { + if (fat->inode[i].type != 0 && bcmp(fname, fat->inode[i].name, BB_INODE16_NAMELEN) == 0) { + // File already exists, error + goto err; + } + if (fat->inode[i].type == 0 && in == NULL) { + // Found a free inode + in = &fat->inode[i]; + } + } + if (in == NULL) { + // Couldn't find a free inode, no space for new file + rv = BBFS_ERR_SPACE; + goto err; + } + + if (len > 64 * BB_FL_BLOCK_SIZE) { + // Large files search low->high in FAT? + b = BBFS_SKSA_LIMIT; + incr = 1; + } else { + // Small files search high->low in FAT? + incr = -1; + b = __osBbFsBlocks - 1; + } + + // Find free blocks to store the file in + in->block = BBFS_BLOCK_EOC; + + for (i = 0; i < (len + BB_FL_BLOCK_SIZE - 1) / BB_FL_BLOCK_SIZE; i++) { + while (b < __osBbFsBlocks && BBFS_NEXT_BLOCK(fat, b) != 0) { + // Search until a free block is found + b += incr; + } + if (b >= __osBbFsBlocks) { + // Exhausted all blocks, no room + goto not_enough_free; + } + + // Mark block as occupied and end of the chain + BBFS_NEXT_BLOCK(fat, b) = BBFS_BLOCK_EOC; + + if (prev != BBFS_BLOCK_FREE) { + // Link prev to new block + BBFS_NEXT_BLOCK(fat, prev) = b; + } else { + // No prev, link inode to first block + in->block = b; + } + prev = b; + } + + // Fill in inode + bcopy(fname, in, BB_INODE16_NAMELEN); + in->type = 1; + in->size = len; + + if (__osBbFsSync(FALSE) == 0) { // Sync fs state to flash? + // Return index of inode as file descriptor + rv = in - fat->inode; + } else { +not_enough_free: + // Not enough free blocks to store the file, or sync to flash failed + + // Revert FAT changes + b = in->block; + while (b != BBFS_BLOCK_EOC) { // While not at the end of the chain + u16 next = BBFS_NEXT_BLOCK(fat, b); + BBFS_NEXT_BLOCK(fat, b) = BBFS_BLOCK_FREE; // mark the block as free + b = next; + } + + // Clear inode + in->block = BBFS_BLOCK_FREE; + in->size = 0; + in->name[0] = '\0'; + + // Return error + rv = BBFS_ERR_SPACE; + } + +err: + __osBbFsRelAccess(); + return rv; +} diff --git a/src/bb/fs/fsdelete.c b/src/bb/fs/fsdelete.c index b9563ae4..3a6d81f7 100644 --- a/src/bb/fs/fsdelete.c +++ b/src/bb/fs/fsdelete.c @@ -19,20 +19,18 @@ s32 osBbFDelete(const char* name) { } rv = BBFS_ERR_ENTRY; - fat = __osBbFat; + for (i = 0; i < BB_INODE16_NUM; i++) { u16 b; if (fat->inode[i].type != 0) { if (bcmp(fname, fat->inode[i].name, BB_INODE16_NAMELEN * sizeof(unsigned char)) == 0) { b = fat->inode[i].block; - while (b != 0xFFFF) { - u16 temp_v0; // not present on mdebug - - temp_v0 = BBFS_NEXT_BLOCK(fat, b); - BBFS_NEXT_BLOCK(fat, b) = 0; - b = temp_v0; + while (b != BBFS_BLOCK_EOC) { + u16 next = BBFS_NEXT_BLOCK(fat, b); + BBFS_NEXT_BLOCK(fat, b) = BBFS_BLOCK_FREE; + b = next; } bzero(&fat->inode[i], sizeof(fat->inode[i])); diff --git a/src/bb/fs/fsdir.c b/src/bb/fs/fsdir.c index e0fbddd6..434cb294 100644 --- a/src/bb/fs/fsdir.c +++ b/src/bb/fs/fsdir.c @@ -6,11 +6,9 @@ s32 osBbFReadDir(OSBbDirEnt* dir, u32 count) { s32 i; s32 j; BbFat16* fat; - OSBbDirEnt* d; + OSBbDirEnt* d = dir; - d = dir; rv = __osBbFsGetAccess(); - if (rv < 0) { return rv; } @@ -18,7 +16,7 @@ s32 osBbFReadDir(OSBbDirEnt* dir, u32 count) { fat = __osBbFat; for (i = 0, j = 0; i < BB_INODE16_NUM; i++) { - unsigned char* var_s2 = fat->inode[i].name; + unsigned char* name = fat->inode[i].name; s32 k; if (fat->inode[i].type == 0) { @@ -30,14 +28,14 @@ s32 osBbFReadDir(OSBbDirEnt* dir, u32 count) { d->type = fat->inode[i].type; d->size = fat->inode[i].size; - for (k = 0; var_s2[k] != '\0' && k < 8; k++) { - d->name[k] = var_s2[k]; + for (k = 0; name[k] != '\0' && k < 8; k++) { + d->name[k] = name[k]; } - if (var_s2[8] != '\0') { + if (name[8] != '\0') { d->name[k] = '.'; - bcopy(&var_s2[8], &d->name[k] + 1, 3); - d->name[k+4] = '\0'; + bcopy(&name[8], &d->name[k] + 1, 3); + d->name[k + 4] = '\0'; } else { d->name[k] = '\0'; } diff --git a/src/bb/fs/fsinit.c b/src/bb/fs/fsinit.c new file mode 100644 index 00000000..b61ba4df --- /dev/null +++ b/src/bb/fs/fsinit.c @@ -0,0 +1,283 @@ +#include "PR/os_internal.h" +#include "PR/bbcard.h" +#include "PR/bbfs.h" + +BbFat16* __osBbFat; +u16 __osBbFatBlock; +u16 __osBbFsBlocks; +static u8 __osBbFsAccessQueueInit; +static OSMesg accessBuf[1]; +static OSMesgQueue __osBbFsAccessQueue; + +u8 __osBbFsAutoSync = TRUE; + +static void createAccessQueue(void) { + __osBbFsAccessQueueInit = TRUE; + osCreateMesgQueue(&__osBbFsAccessQueue, accessBuf, 1); + osSendMesg(&__osBbFsAccessQueue, NULL, OS_MESG_NOBLOCK); +} + +s32 __osBbFsGetAccess(void) { + s32 rv = osBbCardUnhappy(); + if (rv != 0) { + return rv; + } + if (__osBbFat == NULL) { + return BBFS_ERR_UNINIT; + } + + osRecvMesg(&__osBbFsAccessQueue, NULL, OS_MESG_BLOCK); + return 0; +} + +void __osBbFsRelAccess(void) { + osSendMesg(&__osBbFsAccessQueue, NULL, OS_MESG_NOBLOCK); +} + +/** + * Compute a checksum for the FAT contents, rolling 16-bit sum + */ +static u16 csum(void* p) { + u16* x = (u16*)p; + u16 sum = 0; + u16 i; + + for (i = 0; i < sizeof(BbFat16) / sizeof(*x); i++) { + sum += x[i]; + } + return sum; +} + +void __osBbFCheck(void) { + BbFat16* fat = __osBbFat; + BbInode* in; + u16 i; + u16 j; + static u32 map[256]; + BbFatEntry b; + u32 size; + +retry: + bzero(map, sizeof(map)); + + for (i = 0; i < BB_INODE16_NUM; i++) { + in = &fat->inode[i]; + + if (in->type == 0) { + continue; + } + + size = 0; + + for (b = in->block; b != BBFS_BLOCK_EOC; b = BBFS_NEXT_BLOCK(fat, b)) { + if (b < 64) { + goto delete_inode; + } + if (b >= __osBbFsBlocks - BBFS_FAT_LIMIT) { + goto delete_inode; + } + + if (map[b >> 5] & (1 << (b & 0x1F))) { + goto delete_inode; + } + map[b >> 5] |= (1 << (b & 0x1F)); + + size += BB_FL_BLOCK_SIZE; + } + + if (size != in->size) { + goto delete_inode; + } + if (in->name[0] == '\0') { + goto delete_inode; + } + + for (j = 1; j < BB_INODE16_NAMELEN; j++) { + if (in->name[j] != '\0' && (in->name[j] < ' ' || in->name[j] > '~')) { + goto delete_inode; + } + } + continue; + +delete_inode: + bzero(in->name, BB_INODE16_NAMELEN); + in->size = 0; + in->type = 0; + in->block = BBFS_BLOCK_FREE; + goto retry; + } + + for (b = BBFS_SKSA_LIMIT; b < __osBbFsBlocks - BBFS_FAT_LIMIT; b++) { + if (map[b >> 5] & (1 << (b & 0x1F))) { + continue; + } + + if (BBFS_NEXT_BLOCK(fat, b) != BBFS_BLOCK_BAD) { + BBFS_NEXT_BLOCK(fat, b) = BBFS_BLOCK_FREE; + } + } + + for (i = 0; i < BBFS_FAT_LIMIT; i++) { + if (BBFS_NEXT_BLOCK(fat, __osBbFsBlocks - 1 - i) != BBFS_BLOCK_BAD) { + BBFS_NEXT_BLOCK(fat, __osBbFsBlocks - 1 - i) = BBFS_BLOCK_RESERVED; + } + } + + // reserve SKSA + for (i = 0; i < BBFS_SKSA_LIMIT; i++) { + if (BBFS_NEXT_BLOCK(fat, i) != BBFS_BLOCK_BAD) { + BBFS_NEXT_BLOCK(fat, i) = BBFS_BLOCK_RESERVED; + } + } +} + +static s32 __osBbFsReadFat(u16 block, BbFat16* fat, const u8* magic) { + s32 rv; + + // Read NAND block (0x4000 bytes) + rv = osBbCardReadBlock(0, block, fat, NULL); + if (rv == 0) { + // Confirm checksum + if (csum(fat) != BBFS_CHECKSUM_VALUE) { + return 1; + } + // Confirm magic value + if (bcmp(fat->magic, magic, sizeof(fat->magic)) != 0) { + return 1; + } + } + return rv; +} + +static s32 __osBbFsReadFatLinks(BbFat16* fat) { + s32 k; + s32 rv; + + for (k = 1; k < __osBbFsBlocks >> 0xC; k++) { + if (fat[k - 1].link == 0) { + return 1; + } + rv = __osBbFsReadFat(fat[k - 1].link, &fat[k], "BBFL"); + if (rv != 0) { + return rv; + } + if (fat[k - 1].seq != fat[k].seq) { + return 1; + } + } + return 0; +} + +s32 osBbFInit(OSBbFs* fs) { + u32 i; + u32 start; + s32 best = -1; + s32 seq = 0; + s32 rv; + + if (!__osBbFsAccessQueueInit) { + createAccessQueue(); + } + + osRecvMesg(&__osBbFsAccessQueue, NULL, OS_MESG_BLOCK); + osBbCardInit(); + + __osBbFat = NULL; + + rv = osBbCardUnhappy(); + if (rv != 0) { + goto err; + } + + start = (__osBbFsBlocks = osBbCardBlocks(0)) - 1; + +retry: + for (i = 0; i < BBFS_FAT_LIMIT; i++) { + rv = __osBbFsReadFat(start - i, (BbFat16*)fs, "BBFS"); + if (rv == 0) { + rv = __osBbFsReadFatLinks((BbFat16*)fs); + if (rv == 0) { + if (((BbFat16*)fs)->seq >= seq) { + best = i; + seq = ((BbFat16*)fs)->seq; + } + } + } + if (rv < 0 && rv != BBFS_ERR_FAIL) { + goto err; + } + } + + if (best == -1) { + rv = BBFS_ERR_FAIL; + goto err; + } + + if (osBbCardReadBlock(0, start - best, fs, NULL) != 0) { + goto retry; + } + if (csum(fs) != BBFS_CHECKSUM_VALUE) { + goto retry; + } + if (seq != ((BbFat16*)fs)->seq) { + goto retry; + } + if (__osBbFsReadFatLinks((BbFat16*)fs) != 0) { + goto retry; + } + + __osBbFat = (BbFat16*)fs; + __osBbFatBlock = best; + __osBbFsAutoSync = TRUE; + rv = 0; + __osBbFCheck(); + +err: + __osBbFsRelAccess(); + return rv; +} + +s32 osBbFStatFs(OSBbStatFs* statfs) { + u16 b; + u16 i; + u16 j; + s32 rv; + BbFat16* fat; + + rv = __osBbFsGetAccess(); + if (rv < 0) { + return rv; + } + + fat = __osBbFat; + + // Count the number of occupied files + j = 0; + for (i = 0; i < BB_INODE16_NUM; i++) { + if (fat->inode[i].type != 0) { + j++; + } + } + + statfs->files = j; + statfs->freeFiles = BB_INODE16_NUM - j; + + i = j = 0; + for (b = BBFS_SKSA_LIMIT; b < __osBbFsBlocks - BBFS_FAT_LIMIT; b++) { + BbFatEntry next = BBFS_NEXT_BLOCK(fat, b); + + if (next == BBFS_BLOCK_FREE) { + // Count number of free blocks + j++; + } else if (next != BBFS_BLOCK_RESERVED && next != BBFS_BLOCK_BAD) { + // Count number of occupied blocks that are not bad or reserved + i++; + } + } + + statfs->blocks = i; + statfs->freeBlocks = j; + + __osBbFsRelAccess(); + return 0; +} diff --git a/src/bb/fs/fsopen.c b/src/bb/fs/fsopen.c new file mode 100644 index 00000000..1ead19e0 --- /dev/null +++ b/src/bb/fs/fsopen.c @@ -0,0 +1,37 @@ +#include "PR/os_internal.h" +#include "PR/bbcard.h" +#include "PR/bbfs.h" + +s32 osBbFOpen(const char* name, const char* mode) { + unsigned char fname[BB_INODE16_NAMELEN]; + int i; + s32 rv = BBFS_ERR_INVALID; + BbFat16* fat; + + __osBbFsFormatName(fname, name); + if (fname[0] == '\0') { + return rv; + } + + rv = __osBbFsGetAccess(); + if (rv < 0) { + return rv; + } + + fat = __osBbFat; + + // Locate the inode for this file by name + for (i = 0; i < BB_INODE16_NUM; i++) { + if (fat->inode[i].type != 0 && bcmp(fname, fat->inode[i].name, BB_INODE16_NAMELEN) == 0) { + // If found, return the inode index as the file descriptor + rv = i; + goto found; + } + } + // If not found, error + rv = BBFS_ERR_ENTRY; + +found: + __osBbFsRelAccess(); + return rv; +} diff --git a/src/bb/fs/fsread.c b/src/bb/fs/fsread.c index 5dfa9eb8..bb34fd20 100644 --- a/src/bb/fs/fsread.c +++ b/src/bb/fs/fsread.c @@ -1,4 +1,5 @@ #include "PR/os_internal.h" +#include "PR/bbcard.h" #include "PR/bbfs.h" s32 osBbFRead(s32 fd, u32 off, void* buf, u32 len) { @@ -22,43 +23,48 @@ s32 osBbFRead(s32 fd, u32 off, void* buf, u32 len) { in = &fat->inode[fd]; rv = BBFS_ERR_INVALID; - if (in->type != 0 && off % 0x4000 == 0) { - if (off < in->size && off + len >= off) { - if (in->size < off + len) { - len = in->size - off; - } + if (in->type == 0) { + goto end; + } + if (off % BB_FL_BLOCK_SIZE != 0) { + goto end; + } + if (off >= in->size || off + len < off) { + goto end; + } - if (len == 0) { - rv = 0; - goto end; - } + if (in->size < off + len) { + len = in->size - off; + } - b = in->block; + if (len == 0) { + rv = 0; + goto end; + } - for (i = 0; i < off / 0x4000; i++) { - b = BBFS_NEXT_BLOCK(fat, b); - } + b = in->block; + for (i = 0; i < off / BB_FL_BLOCK_SIZE; i++) { + b = BBFS_NEXT_BLOCK(fat, b); + } - count = 0; + count = 0; + while (len != 0) { + if (b == BBFS_BLOCK_FREE || b >= __osBbFsBlocks - BBFS_FAT_LIMIT) { + goto end; + } - while (len != 0) { - if (b == 0 || b >= __osBbFsBlocks - 0x10) { - goto end; - } + rv = osBbCardReadBlock(0, b, buf, NULL); + if (rv < 0) { + goto end; + } - rv = osBbCardReadBlock(0, b, buf, NULL); - if (rv < 0) { - goto end; - } + b = BBFS_NEXT_BLOCK(fat, b); - b = BBFS_NEXT_BLOCK(fat, b); - buf += 0x4000; - len = (len > 0x4000) ? (len - 0x4000) : 0; - count += 0x4000; - } - rv = count; - } + buf += BB_FL_BLOCK_SIZE; + len = (len > BB_FL_BLOCK_SIZE) ? (len - BB_FL_BLOCK_SIZE) : 0; + count += BB_FL_BLOCK_SIZE; } + rv = count; end: __osBbFsRelAccess(); diff --git a/src/bb/fs/fsrename.c b/src/bb/fs/fsrename.c index 553f4c6b..c76a1471 100644 --- a/src/bb/fs/fsrename.c +++ b/src/bb/fs/fsrename.c @@ -5,14 +5,11 @@ s32 osBbFRename(const char* old, const char* new) { unsigned char fold[BB_INODE16_NAMELEN]; unsigned char fnew[BB_INODE16_NAMELEN]; s32 rv; - s32 inew; - s32 iold; + s32 inew = -1; + s32 iold = -1; BbFat16* fat; int i; - inew = -1; - iold = -1; - __osBbFsFormatName(fold, old); __osBbFsFormatName(fnew, new); @@ -40,17 +37,13 @@ s32 osBbFRename(const char* old, const char* new) { rv = BBFS_ERR_ENTRY; if (iold != -1) { if (inew != -1) { - u16 b; - - b = fat->inode[inew].block; - while (b != 0xFFFF) { - u16 temp; - - temp = BBFS_NEXT_BLOCK(fat, b); - BBFS_NEXT_BLOCK(fat, b) = 0; - b = temp; + u16 b = fat->inode[inew].block; + while (b != BBFS_BLOCK_EOC) { + u16 next = BBFS_NEXT_BLOCK(fat, b); + BBFS_NEXT_BLOCK(fat, b) = BBFS_BLOCK_FREE; + b = next; } - bzero(&fat->inode[inew], 0x14); + bzero(&fat->inode[inew], sizeof(BbInode)); } bcopy(fnew, fat->inode[iold].name, BB_INODE16_NAMELEN * sizeof(unsigned char)); diff --git a/src/bb/fs/fsstat.c b/src/bb/fs/fsstat.c index 76a89f43..53967cd4 100644 --- a/src/bb/fs/fsstat.c +++ b/src/bb/fs/fsstat.c @@ -17,22 +17,25 @@ s32 osBbFStat(s32 fd, OSBbStatBuf* sb, u16* blockList, u32 listLen) { } rv = BBFS_ERR_INVALID; - fat = __osBbFat; - in = &fat->inode[fd]; + // Access the inode for this file, skip and error if the inode is marked as free + in = &fat->inode[fd]; if (in->type != 0) { + // Retrieve file type and size sb->type = in->type; sb->size = in->size; + // If the caller requested a NAND block list, build one if (blockList != NULL && listLen != 0) { + // Visit all blocks linked in the FAT until the list length or the blocks are exhausted u16 b = in->block; - - for (i = 0; b != 0xFFFF && i < listLen; i++) { + for (i = 0; b != BBFS_BLOCK_EOC && i < listLen; i++) { blockList[i] = b; b = BBFS_NEXT_BLOCK(fat, b); } + // If the list was not filled to capacity, fill the remainder with 0s if (i < listLen) { blockList[i] = 0; } diff --git a/src/bb/fs/fssync.c b/src/bb/fs/fssync.c new file mode 100644 index 00000000..6cd5d714 --- /dev/null +++ b/src/bb/fs/fssync.c @@ -0,0 +1,68 @@ +#include "PR/os_internal.h" +#include "PR/bbcard.h" +#include "PR/bbfs.h" + +s32 __osBbFsSync(int force) { + BbFat16* fat = __osBbFat; + u32 target = __osBbFatBlock; + u16 sum; + u16* p; + u16 link = 0; + int tries; + int k; + + if (!force && !__osBbFsAutoSync) { + return 0; + } + + k = __osBbFsBlocks >> 0xC; + while (--k >= 0) { + fat[k].seq++; + fat[k].link = link; + fat[k].cksum = 0; + + // Compute new checksum + sum = 0; + for (p = &fat[k].entry[0]; p < &fat[k].entry[8192]; p++) { // wtf? + sum += *p; + } + fat[k].cksum = BBFS_CHECKSUM_VALUE - sum; + + // Write the FAT to the card + for (tries = 0; tries < 16; tries++) { + target++; + if (target >= BBFS_FAT_LIMIT) { + target = 0; + } + + link = __osBbFsBlocks - target - 1; + if (osBbCardEraseBlock(0, link) == 0 && + osBbCardWriteBlock(0, __osBbFsBlocks - target - 1, &fat[k], NULL) == 0) { + goto success; + } + // retry + } + // ran out of retries + return BBFS_ERR_FAIL; +success:; + } + __osBbFatBlock = target; + return 0; +} + +s32 osBbFAutoSync(u32 on) { + __osBbFsAutoSync = on; + return 0; +} + +s32 osBbFSync(void) { + s32 rv = __osBbFsGetAccess(); + if (rv < 0) { + return rv; + } + + rv = __osBbFsSync(TRUE); + + __osBbFsRelAccess(); + return rv; +} diff --git a/src/bb/fs/fswrite.c b/src/bb/fs/fswrite.c index 5e80e6fa..050f8d5d 100644 --- a/src/bb/fs/fswrite.c +++ b/src/bb/fs/fswrite.c @@ -1,19 +1,17 @@ #include "PR/os_internal.h" #include "PR/bbfs.h" #include "PR/os_bbcard.h" +#include "macros.h" u16 __osBbFReallocBlock(BbInode* in, u16 block, u16 newVal) { u16 b; u16 ob; - u16 prev; + u16 prev = BBFS_BLOCK_FREE; s32 incr; - BbFat16* fat; - - prev = 0; - fat = __osBbFat; + BbFat16* fat = __osBbFat; - if (in->size > 0x100000) { - ob = 0x40; + if (in->size > 64 * BB_FL_BLOCK_SIZE) { + ob = BBFS_SKSA_LIMIT; incr = 1; } else { incr = -1; @@ -21,11 +19,11 @@ u16 __osBbFReallocBlock(BbInode* in, u16 block, u16 newVal) { } if (ob >= __osBbFsBlocks) { - return 0xFFFE; + return BBFS_BLOCK_BAD; } while (ob < __osBbFsBlocks) { - if (BBFS_NEXT_BLOCK(fat, ob) == 0) { + if (BBFS_NEXT_BLOCK(fat, ob) == BBFS_BLOCK_FREE) { break; } ob += incr; @@ -37,7 +35,8 @@ u16 __osBbFReallocBlock(BbInode* in, u16 block, u16 newVal) { prev = b; b = BBFS_NEXT_BLOCK(fat, b); } - if (prev != 0) { + + if (prev != BBFS_BLOCK_FREE) { BBFS_NEXT_BLOCK(fat, prev) = ob; } else { in->block = ob; @@ -45,12 +44,12 @@ u16 __osBbFReallocBlock(BbInode* in, u16 block, u16 newVal) { BBFS_NEXT_BLOCK(fat, ob) = BBFS_NEXT_BLOCK(fat, b); BBFS_NEXT_BLOCK(fat, b) = newVal; + if (__osBbFsSync(FALSE) == 0) { return ob; } } - - return 0xFFFE; + return BBFS_BLOCK_BAD; } s32 osBbFWrite(s32 fd, u32 off, void* buf, u32 len) { @@ -63,7 +62,7 @@ s32 osBbFWrite(s32 fd, u32 off, void* buf, u32 len) { u16 blocks[4]; u16 n; - if ((u32) fd >= BB_INODE16_NUM) { + if (fd < 0 || fd >= BB_INODE16_NUM) { return BBFS_ERR_INVALID; } @@ -76,61 +75,76 @@ s32 osBbFWrite(s32 fd, u32 off, void* buf, u32 len) { in = &fat->inode[fd]; rv = BBFS_ERR_INVALID; - if (in->type != 0 && off % 0x4000 == 0 && off < in->size) { - if (len % 0x4000 == 0 && off + len >= off && in->size >= off + len) { - if (len == 0) { - rv = 0; - goto end; - } + if (in->type == 0) { + goto end; + } + if (off % BB_FL_BLOCK_SIZE != 0) { + goto end; + } + if (off >= in->size) { + goto end; + } + if (len % BB_FL_BLOCK_SIZE != 0) { + goto end; + } + if (off + len < off) { + goto end; + } + if (in->size < off + len) { + goto end; + } - b = in->block; - for (i = 0; i < off / 0x4000; i++) { - b = BBFS_NEXT_BLOCK(fat, b); + if (len == 0) { + rv = 0; + goto end; + } + + b = in->block; + for (i = 0; i < off / BB_FL_BLOCK_SIZE; i++) { + b = BBFS_NEXT_BLOCK(fat, b); + } + + count = 0; + while (len != 0) { + for (n = 0; len != 0 && n < ARRLEN(blocks); n++) { + if (b == BBFS_BLOCK_FREE || b >= __osBbFsBlocks - BBFS_FAT_LIMIT) { + goto end; } - count = 0; + blocks[n] = b; + b = BBFS_NEXT_BLOCK(fat, b); - while (len != 0) { - for (n = 0; len != 0 && n < 4; n++) { - if ((b == 0) || (b >= __osBbFsBlocks - 0x10)) { - goto end; - } + len = (len > BB_FL_BLOCK_SIZE) ? (len - BB_FL_BLOCK_SIZE) : 0; + count += BB_FL_BLOCK_SIZE; + } - blocks[n] = b; - b = BBFS_NEXT_BLOCK(fat, b); + if ((rv = osBbCardEraseBlocks(0, blocks, n)) < 0 || + (rv = osBbCardWriteBlocks(0, blocks, n, buf, NULL)) < 0) { + int i; - len = (len > 0x4000) ? (len - 0x4000) : 0; - count += 0x4000; - } + if (rv != BBFS_ERR_FAIL) { + goto end; + } - if (((rv = osBbCardEraseBlocks(0, blocks, n)) < 0) || (rv = osBbCardWriteBlocks(0, blocks, n, buf, NULL)) < 0) { - int i; + for (i = 0; i < n; i++) { + u16 b = blocks[i]; + retry: + if ((rv = osBbCardEraseBlock(0, b)) < 0 || + (rv = osBbCardWriteBlock(0, b, buf + i * BB_FL_BLOCK_SIZE, NULL)) < 0) { if (rv != BBFS_ERR_FAIL) { goto end; } - - for(i = 0; i < n; i++) { - u16 b = blocks[i]; - - retry: - if ((rv = osBbCardEraseBlock(0, b)) < 0 || ((rv = osBbCardWriteBlock(0, b, buf + i * 0x4000, NULL)) < 0)) { - if (rv != BBFS_ERR_FAIL) { - goto end; - } - if ((b = __osBbFReallocBlock(in, b, 0xFFFE)) == 0xFFFE) { - goto end; - } - goto retry; - } + if ((b = __osBbFReallocBlock(in, b, BBFS_BLOCK_BAD)) == BBFS_BLOCK_BAD) { + goto end; } + goto retry; } - buf += n * 0x4000; } - - rv = count; } + buf += n * BB_FL_BLOCK_SIZE; } + rv = count; end: __osBbFsRelAccess(); diff --git a/src/bb/misc/execfile.c b/src/bb/misc/execfile.c index db6e591a..8dad6491 100644 --- a/src/bb/misc/execfile.c +++ b/src/bb/misc/execfile.c @@ -1,6 +1,7 @@ #include "PR/os_internal.h" #include "PR/os_pi.h" #include "PR/bcp.h" +#include "PR/bbcard.h" #include "macros.h" #include "../usb/usb.h" @@ -56,7 +57,7 @@ u32 osBbLoadApp(OSBbLaunchMetaData* md, u16* blockList, s32 listSize, s32 loadAl handler = osCartRomInit(); IO_WRITE(PI_44_REG, 0); - IO_WRITE(PI_48_REG, 0x1F008BFF); + IO_WRITE(PI_48_REG, NAND_ATB_CONFIG(0, TRUE)); // Read app entry point from ROM header osEPiReadIo(handler, 8, &addr); @@ -178,7 +179,7 @@ s32 osBbExecFile(s32 fd, char* name, OSBbLaunchMetaData* md, u8* buffer) { IO_WRITE(PI_50_REG, 0); IO_WRITE(PI_44_REG, 0); - IO_WRITE(PI_48_REG, 0x1F008BFF); + IO_WRITE(PI_48_REG, NAND_ATB_CONFIG(0, TRUE)); // Read game entry point from ROM header osEPiReadIo(handler, 8, &addr); diff --git a/src/bb/misc/state.c b/src/bb/misc/state.c index 1e361649..88700658 100644 --- a/src/bb/misc/state.c +++ b/src/bb/misc/state.c @@ -1,5 +1,6 @@ #include "PR/os_internal.h" #include "PR/bcp.h" +#include "PR/bbcard.h" #include "memory.h" #include "macros.h" @@ -392,7 +393,7 @@ s32 osBbGetLaunchMetaData(OSBbLaunchMetaData* md, u16* blockList, s32 listSize) // ? IO_WRITE(PI_50_REG, 0); IO_WRITE(PI_44_REG, 0); - IO_WRITE(PI_48_REG, 0x1F008BFF); + IO_WRITE(PI_48_REG, NAND_ATB_CONFIG(0, TRUE)); // Read the CMD from the end of the block with programmed IO reads for (i = 0x4000 - sizeof(*md); i < 0x4000; i += 4) { diff --git a/src/os/exceptasm.s b/src/os/exceptasm.s index 0fd2f59f..5f4234cd 100644 --- a/src/os/exceptasm.s +++ b/src/os/exceptasm.s @@ -12,6 +12,7 @@ #define KMC_STAT 0xBFF08004 #ifdef BBPLAYER +#include "PR/bcp.h" .set mips3 #endif @@ -615,7 +616,7 @@ cart: jal send_mesg #else - lw s1, PHYS_TO_K1(MI_BASE_REG + 0x38) + lw s1, PHYS_TO_K1(MI_38_REG) flash: andi t1, s1, 0x40 @@ -623,7 +624,7 @@ flash: andi s1, s1, 0x3f80 li t1, 0 - sw t1, PHYS_TO_K1(PI_BASE_REG + 0x48) + sw t1, PHYS_TO_K1(PI_48_REG) li a0, MESG(OS_EVENT_FLASH) jal send_mesg flashx: @@ -634,7 +635,7 @@ md: andi s1, s1, 0x1fc0 li t1, 0x2000 - sw t1, PHYS_TO_K1(MI_BASE_REG + 0x38) + sw t1, PHYS_TO_K1(MI_38_REG) li a0, MESG(OS_EVENT_MD) jal send_mesg mdx: @@ -645,7 +646,7 @@ aes: andi s1, s1, 0x3f40 li t1, 0x4000 - sw t1, PHYS_TO_K1(MI_BASE_REG + 0x3C) + sw t1, PHYS_TO_K1(MI_3C_REG) li a0, MESG(OS_EVENT_AES) jal send_mesg aesx: @@ -656,7 +657,7 @@ ide: andi s1, s1, 0x3ec0 li t1, 0x10000 - sw t1, PHYS_TO_K1(MI_BASE_REG + 0x3C) + sw t1, PHYS_TO_K1(MI_3C_REG) li a0, MESG(OS_EVENT_IDE) jal send_mesg idex: @@ -667,7 +668,7 @@ pi_err: andi s1, s1, 0x3dc0 li t1, 0x40000 - sw t1, PHYS_TO_K1(MI_BASE_REG + 0x3C) + sw t1, PHYS_TO_K1(MI_3C_REG) li a0, MESG(OS_EVENT_PI_ERR) jal send_mesg pi_errx: @@ -678,7 +679,7 @@ usb0: andi s1, s1, 0x3bc0 li t1, 0x100000 - sw t1, PHYS_TO_K1(MI_BASE_REG + 0x3C) + sw t1, PHYS_TO_K1(MI_3C_REG) li a0, MESG(OS_EVENT_USB0) jal send_mesg usb0x: @@ -689,7 +690,7 @@ usb1: andi s1, s1, 0x37c0 li t1, 0x400000 - sw t1, PHYS_TO_K1(MI_BASE_REG + 0x3C) + sw t1, PHYS_TO_K1(MI_3C_REG) li a0, MESG(OS_EVENT_USB1) jal send_mesg usb1x: diff --git a/tools/disassemble_elf.py b/tools/disassemble_elf.py index e38bedb4..24e6248c 100755 --- a/tools/disassemble_elf.py +++ b/tools/disassemble_elf.py @@ -237,7 +237,7 @@ def add_end(vaddr, sym): # Apply relocation if len(rels) != 0: - rel = rels[0] + rel : Relocation = rels[0] if rel.rel_type == R_MIPS_26: if insn.id == MIPS_INS_JAL: op_str = rel.relocated_symbol.name @@ -265,9 +265,17 @@ def add_end(vaddr, sym): assert insn.id in [MIPS_INS_LUI] rel_name = rel.relocated_symbol.name if rel.relocated_symbol.type == ST_SECTION: - rel_name = f".{rel_name[1].upper()}_00000000" - if cur_fdr is not None: - pass + for sym in self.elf_file.symtab.symbol_entries: + sym : Symbol + + if sym.type == ST_SECTION: + continue + + if sym.parent_section is not None and sym.parent_section.name == rel.relocated_symbol.name: + if sym.st_value == rel.r_addend: + break + + rel_name = sym.name op_str = f"{insn.abi.gpr_names[insn.rt]}, %hi({rel_name})" elif rel.rel_type == R_MIPS_LO16: