diff --git a/firmware/include/fsystem.h b/firmware/include/fsystem.h index f8d50f2..775c481 100644 --- a/firmware/include/fsystem.h +++ b/firmware/include/fsystem.h @@ -558,6 +558,17 @@ extern int FSGetVolumeSize(int Volnumber); */ extern int FSGetVolumeFree(int Volnumber); +/*! + * \brief Mark current volume as read-only. Use immediately after mount. + * + * Mark current volume as read-only. Use immediately after mount. + * + * \param Volnumber Number of the volume (0-3) + * \return Nothing. + * \sa FSSetCurrentVolume + */ +extern void FSMarkVolumeReadOnly(); + // DIRECTORY ACCESS FUNCTIONS /*! diff --git a/firmware/sys/fsystem/fsflushbuffers.c b/firmware/sys/fsystem/fsflushbuffers.c index 7fc32a9..d3f1e4f 100644 --- a/firmware/sys/fsystem/fsflushbuffers.c +++ b/firmware/sys/fsystem/fsflushbuffers.c @@ -44,14 +44,15 @@ int FSFlushBuffers(FS_FILE * file) } -// WRITE UPDATED DIRECTORY ENTRY IF FILE HAS CHANGED - if(file->Dir) { + fs = FSystem.Volumes[file->Volume]; + +// WRITE UPDATED DIRECTORY ENTRY IF FILE HAS CHANGED, BUT ONLY IF THE VOLUME IS NOT MOUNTED READ-ONLY + if((file->Dir) && !(fs->InitFlags&VOLFLAG_READONLY)) { error = FSUpdateDirEntry(file); if(error != FS_OK) return error; } - fs = FSystem.Volumes[file->Volume]; // FLUSH ALL FAT CHAINS error = FSFlushFATCache(fs); diff --git a/firmware/sys/fsystem/fsflushfatcache.c b/firmware/sys/fsystem/fsflushfatcache.c index 7018a3e..cfe7a88 100644 --- a/firmware/sys/fsystem/fsflushfatcache.c +++ b/firmware/sys/fsystem/fsflushfatcache.c @@ -48,6 +48,7 @@ int FSFlushFATCache(FS_VOLUME * fs) FSPatchFATBlock(sector, bl + 1, sectaddr, fs, TRUE); // PATCH AND FLUSH ENTRIES // WRITE TO ALL ACTIVE FATS + if(!(fs->InitFlags&VOLFLAG_READONLY)) { for(f = fs->NumFATS - 1; f >= 0; --f) { error = SDDWrite((((uint64_t) fs->FirstFATAddr) << 9) + sectaddr + @@ -59,6 +60,7 @@ int FSFlushFATCache(FS_VOLUME * fs) return FS_ERROR; } } + } } simpfree(sector); diff --git a/firmware/sys/fsystem/fsmountvolume.c b/firmware/sys/fsystem/fsmountvolume.c index 0d47827..e0fec29 100644 --- a/firmware/sys/fsystem/fsmountvolume.c +++ b/firmware/sys/fsystem/fsmountvolume.c @@ -255,10 +255,12 @@ int FSMountVolume(SD_CARD * Disk, FS_VOLUME * fs, int VolNumber) } // UPDATE HINTS AS NEEDED AND MARK AS CLEAN -int FSUpdateHints(FS_VOLUME * fs) +int FSUpdateHints(FS_VOLUME * fs) { unsigned char *TempData; int err, written = 0; + if(fs->InitFlags & VOLFLAG_READONLY) + return FS_OK; if(!(fs->InitFlags & VOLFLAG_HINTDIRTY)) return FS_OK; @@ -317,4 +319,12 @@ int FSUpdateHints(FS_VOLUME * fs) return FS_OK; } + +void FSMarkVolumeReadOnly() +{ + FS_VOLUME *fs; + if(FSystem.Volumes[FSystem.CurrentVolume] != NULL) + FSystem.Volumes[FSystem.CurrentVolume]->InitFlags |= VOLFLAG_READONLY; +} + #endif diff --git a/firmware/sys/fsystem/fswritell.c b/firmware/sys/fsystem/fswritell.c index da9cd36..116b15b 100644 --- a/firmware/sys/fsystem/fswritell.c +++ b/firmware/sys/fsystem/fswritell.c @@ -17,6 +17,16 @@ int FSWriteLL(unsigned char *buffer, int nbytes, FS_FILE * file, FS_VOLUME * fs) uint64_t currentaddr; FS_FRAGMENT *fr; + // ******** + // DEBUG ONLY: REMOVE ASAP + + if(nbytes && (fs->InitFlags & VOLFLAG_READONLY)) { + throw_dbgexception("Attempt to write Read-only volume",__EX_CONT | __EX_WARM | __EX_RESET); + } + + // ******** + + if(file->CurrentOffset + nbytes > file->FileSize) { if(file->Mode & FSMODE_NOGROW) return FS_DISKFULL; // FILE EXPANSION NOT ALLOWED diff --git a/firmware/sys/fsystem/fsyspriv.h b/firmware/sys/fsystem/fsyspriv.h index c1c4938..0a3a009 100644 --- a/firmware/sys/fsystem/fsyspriv.h +++ b/firmware/sys/fsystem/fsyspriv.h @@ -121,6 +121,7 @@ extern void FSGetDateTime(unsigned int *datetime, unsigned int *hundredths); // VOLUME FUNCTIONS extern int FSMountVolume(SD_CARD * Disk, FS_VOLUME * fs, int VolNumber); +extern void FSMarkVolumeReadOnly(); extern int FSVolumePresent(FS_VOLUME * fs); extern int FSCalcFreeSpace(FS_VOLUME * fs); extern int FSUpdateHints(FS_VOLUME * fs); diff --git a/firmware/sys/target_prime1/boot_multiload.c b/firmware/sys/target_prime1/boot_multiload.c index 42fba41..53cc852 100644 --- a/firmware/sys/target_prime1/boot_multiload.c +++ b/firmware/sys/target_prime1/boot_multiload.c @@ -110,6 +110,8 @@ int load_os(char *name) while(1); } + FSMarkVolumeReadOnly(); + FS_FILE *fileptr; err = FSOpen(name, FSMODE_READ | FSMODE_NOCREATE, &fileptr); diff --git a/firmware/sys/target_prime1/nand.c b/firmware/sys/target_prime1/nand.c index 3a8f16e..4984082 100644 --- a/firmware/sys/target_prime1/nand.c +++ b/firmware/sys/target_prime1/nand.c @@ -30,6 +30,8 @@ #define NFECCERR0_ECCReady 0x40000000 #define NAND_STATUS_FAIL 0x01 +#define NAND_STATUS_WRITEPROTECT 0x80 +#define NAND_STATUS_READY 0x40 #define NAND_CMD_READ1st 0x00 #define NAND_CMD_READ2nd 0x30 @@ -339,6 +341,7 @@ static void __attribute__ ((noinline)) busy_wait(unsigned int count) static int NANDCheckWrite(void) { if ((*NFSTAT & NFSTAT_IllegalAccess) != 0) { + throw_dbgexception("Illegal NAND access",__EX_CONT); return 0; } @@ -347,10 +350,24 @@ static int NANDCheckWrite(void) busy_wait(3); for (int i = 0; i < 1024; ++i) { + + // Make sure we are no longer busy + if ((*NFDATA_8 & NAND_STATUS_READY) == 0) { + continue; + } + + // Also check for write protection + if ((*NFDATA_8 & NAND_STATUS_WRITEPROTECT) == 0) { + throw_dbgexception("NAND is write protected",__EX_CONT); + return 0; + } + // Finally, check for pass/fail if ((*NFDATA_8 & NAND_STATUS_FAIL) == 0) { return 1; } } + throw_dbgexception("NAND Block Erase Failed.",__EX_CONT); + // Should never happen return 0; } @@ -494,6 +511,10 @@ int NANDInit(void) *GPMCON = (*GPMCON & ~0xc) | 0x8; // Set GPM1 as FRnB (NAND ready/busy signal) + *GPLCON = (*GPLCON & ~0x0C000000) | 0x4000000; // Set GPL13 as output, connected to WP (NAND write protect) + *GPLUDP = (*GPLUDP & ~0x0C000000) ; // Disable pull up/down + *GPLDAT |= 0x2000; // Active high = write enabled + *NFSTAT = 0x70; // Clear all flags NANDReset(); diff --git a/firmware/sys/target_prime1/sddriver.c b/firmware/sys/target_prime1/sddriver.c index 52aac08..e19c602 100644 --- a/firmware/sys/target_prime1/sddriver.c +++ b/firmware/sys/target_prime1/sddriver.c @@ -63,5 +63,5 @@ int SDIOSetup(SD_CARD * card, int shutdown) int SDCardWriteProtected() { - return TRUE; + return FALSE; }