|
|
|
@ -21,6 +21,7 @@
|
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
|
|
|
#include "opentx.h"
|
|
|
|
|
#include "FatFs/diskio.h"
|
|
|
|
|
#include "stamp.h"
|
|
|
|
|
|
|
|
|
|
#if defined(__cplusplus) && !defined(SIMU)
|
|
|
|
|
extern "C" {
|
|
|
|
@ -31,9 +32,7 @@ extern "C" {
|
|
|
|
|
|
|
|
|
|
enum MassstorageLuns {
|
|
|
|
|
STORAGE_SDCARD_LUN,
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
STORAGE_EEPROM_LUN,
|
|
|
|
|
#endif
|
|
|
|
|
STORAGE_LUN_NBR
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -52,7 +51,6 @@ const unsigned char STORAGE_Inquirydata[] = { //36
|
|
|
|
|
USB_PRODUCT, /* Product : 16 Bytes */
|
|
|
|
|
'R', 'a', 'd', 'i', 'o', ' ', ' ', ' ',
|
|
|
|
|
'1', '.', '0', '0', /* Version : 4 Bytes */
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
/* LUN 1 */
|
|
|
|
|
0x00,
|
|
|
|
|
0x80,
|
|
|
|
@ -66,13 +64,12 @@ const unsigned char STORAGE_Inquirydata[] = { //36
|
|
|
|
|
USB_PRODUCT, /* Product : 16 Bytes */
|
|
|
|
|
'R', 'a', 'd', 'i', 'o', ' ', ' ', ' ',
|
|
|
|
|
'1', '.', '0' ,'0', /* Version : 4 Bytes */
|
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
#define RESERVED_SECTORS (1 /*Boot*/ + 2 /*Fat table */ + 1 /*Root dir*/ + 8 /* one cluster for firmware.txt */)
|
|
|
|
|
|
|
|
|
|
int32_t fat12Write(const uint8_t * buffer, uint16_t sector, uint16_t count);
|
|
|
|
|
int32_t fat12Read(uint8_t * buffer, uint16_t sector, uint16_t count );
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int8_t STORAGE_Init (uint8_t lun);
|
|
|
|
|
|
|
|
|
@ -140,13 +137,15 @@ int8_t STORAGE_Init (uint8_t lun)
|
|
|
|
|
*/
|
|
|
|
|
int8_t STORAGE_GetCapacity (uint8_t lun, uint32_t *block_num, uint32_t *block_size)
|
|
|
|
|
{
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
if (lun == STORAGE_EEPROM_LUN) {
|
|
|
|
|
*block_size = BLOCK_SIZE;
|
|
|
|
|
*block_num = 3 + EEPROM_SIZE/BLOCK_SIZE + FLASHSIZE/BLOCK_SIZE;
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
*block_num = RESERVED_SECTORS + EEPROM_SIZE/BLOCK_SIZE + FLASHSIZE/BLOCK_SIZE;
|
|
|
|
|
#else
|
|
|
|
|
*block_num = RESERVED_SECTORS + FLASHSIZE/BLOCK_SIZE;
|
|
|
|
|
#endif
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (!SD_CARD_PRESENT())
|
|
|
|
|
return -1;
|
|
|
|
@ -171,9 +170,7 @@ uint8_t lunReady[STORAGE_LUN_NBR];
|
|
|
|
|
void usbPluggedIn()
|
|
|
|
|
{
|
|
|
|
|
lunReady[STORAGE_SDCARD_LUN] = 1;
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
lunReady[STORAGE_EEPROM_LUN] = 1;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -218,11 +215,9 @@ int8_t STORAGE_Read (uint8_t lun,
|
|
|
|
|
{
|
|
|
|
|
WATCHDOG_SUSPEND(100/*1s*/);
|
|
|
|
|
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
if (lun == STORAGE_EEPROM_LUN) {
|
|
|
|
|
return (fat12Read(buf, blk_addr, blk_len) == 0) ? 0 : -1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// read without cache
|
|
|
|
|
return (__disk_read(0, buf, blk_addr, blk_len) == RES_OK) ? 0 : -1;
|
|
|
|
@ -243,11 +238,9 @@ int8_t STORAGE_Write (uint8_t lun,
|
|
|
|
|
{
|
|
|
|
|
WATCHDOG_SUSPEND(100/*1s*/);
|
|
|
|
|
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
if (lun == STORAGE_EEPROM_LUN) {
|
|
|
|
|
return (fat12Write(buf, blk_addr, blk_len) == 0) ? 0 : -1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// write without cache
|
|
|
|
|
return (__disk_write(0, buf, blk_addr, blk_len) == RES_OK) ? 0 : -1;
|
|
|
|
@ -264,24 +257,53 @@ int8_t STORAGE_GetMaxLun (void)
|
|
|
|
|
return STORAGE_LUN_NBR - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
|
|
|
|
|
/* Firmware.txt */
|
|
|
|
|
const char firmware_txt[] =
|
|
|
|
|
#if defined(BOOT)
|
|
|
|
|
"OpenTX Bootloader"
|
|
|
|
|
#else
|
|
|
|
|
"OpenTX Firmware"
|
|
|
|
|
#endif
|
|
|
|
|
" for " FLAVOUR "\r\n\r\n"
|
|
|
|
|
#if defined(BOOT)
|
|
|
|
|
"BOOTVER "
|
|
|
|
|
#else
|
|
|
|
|
"FWVERSION "
|
|
|
|
|
#endif
|
|
|
|
|
"opentx-" FLAVOUR "-" VERSION " (" GIT_STR ")\r\n"
|
|
|
|
|
"DATE " DATE "\r\n"
|
|
|
|
|
"TIME " TIME "\r\n"
|
|
|
|
|
"req SD ver " REQUIRED_SDCARD_VERSION "\r\n"
|
|
|
|
|
#if !defined(BOOT)
|
|
|
|
|
"BOOTVER "
|
|
|
|
|
#else
|
|
|
|
|
"FWVERSION "
|
|
|
|
|
#endif
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
/**
|
|
|
|
|
* FAT12 boot sector partition.
|
|
|
|
|
*/
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
#define TOTALSECTORS (RESERVED_SECTORS + (EEPROM_SIZE/BLOCK_SIZE) + (FLASHSIZE/BLOCK_SIZE))
|
|
|
|
|
#else
|
|
|
|
|
#define TOTALSECTORS (RESERVED_SECTORS + (FLASHSIZE/BLOCK_SIZE))
|
|
|
|
|
#endif
|
|
|
|
|
const char g_FATboot[BLOCK_SIZE] =
|
|
|
|
|
{
|
|
|
|
|
0xeb, 0x3c, 0x90, // Jump instruction.
|
|
|
|
|
0x39, 0x58, 0x20, 0x54, 0x45, 0x41, 0x4D, 0x00, // OEM Name
|
|
|
|
|
'O', 'p', 'e', 'n', 'T', 'x', 0x00, 0x00, // OEM Name
|
|
|
|
|
0x00, 0x02, // Bytes per sector
|
|
|
|
|
0x08, // Sectors per FS cluster.
|
|
|
|
|
0x01, 0x00, // Reserved sector count
|
|
|
|
|
|
|
|
|
|
0x01, // Number of FATs
|
|
|
|
|
0x10, 0x00, // Number of root directory entries
|
|
|
|
|
3+(EEPROM_SIZE/BLOCK_SIZE), (FLASHSIZE/BLOCK_SIZE)>>8, // Total sectors
|
|
|
|
|
TOTALSECTORS & 0x00ff, (TOTALSECTORS & 0xff00) >> 8, // Total sectors
|
|
|
|
|
0xf8, // Media descriptor
|
|
|
|
|
0x01, 0x00, // Sectors per FAT table
|
|
|
|
|
0x02, 0x00, // Sectors per FAT table
|
|
|
|
|
0x20, 0x00, // Sectors per track
|
|
|
|
|
0x40, 0x00, // Number of heads
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, // Number of hidden sectors
|
|
|
|
@ -290,9 +312,9 @@ const char g_FATboot[BLOCK_SIZE] =
|
|
|
|
|
0x00, // Physical drive number
|
|
|
|
|
0x00, // Reserved
|
|
|
|
|
0x29, // Extended boot signature
|
|
|
|
|
0xCE, 0xFA, 0x5C, 0xD1, // Disk ID (serial number)
|
|
|
|
|
0x56, 0x49, 0x52, 0x54, 0x46, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, // Volume label
|
|
|
|
|
0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, // FAT file system type
|
|
|
|
|
'O', 'T', 'x', 0xD1, // Disk ID (serial number)
|
|
|
|
|
'V', 'I', 'R', 'T', 'F', 'S', ' ', ' ', ' ', ' ', ' ', // Volume label
|
|
|
|
|
'F', 'A', 'T', '1', '2', ' ', ' ', ' ', // FAT file system type
|
|
|
|
|
0x00, 0x00, // OS boot code
|
|
|
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
@ -327,79 +349,6 @@ const char g_FATboot[BLOCK_SIZE] =
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#if defined(REV4a)
|
|
|
|
|
const char g_FAT[BLOCK_SIZE] =
|
|
|
|
|
{
|
|
|
|
|
0xF8, 0xFF, 0xFF, 0x03, 0x40, 0x00, 0x05, 0x60, 0x00, 0x07, 0x80, 0x00, 0x09, 0xA0, 0x00, 0x0B,
|
|
|
|
|
0xC0, 0x00, 0x0D, 0xE0, 0x00, 0x0F, 0x00, 0x01, 0x11, 0xF0, 0xFF, 0x13, 0x40, 0x01, 0x15, 0x60,
|
|
|
|
|
0x01, 0x17, 0x80, 0x01, 0x19, 0xA0, 0x01, 0x1B, 0xC0, 0x01, 0x1D, 0xE0, 0x01, 0x1F, 0x00, 0x02,
|
|
|
|
|
0x21, 0x20, 0x02, 0x23, 0x40, 0x02, 0x25, 0x60, 0x02, 0x27, 0x80, 0x02, 0x29, 0xA0, 0x02, 0x2B,
|
|
|
|
|
0xC0, 0x02, 0x2D, 0xE0, 0x02, 0x2F, 0x00, 0x03, 0x31, 0x20, 0x03, 0x33, 0x40, 0x03, 0x35, 0x60,
|
|
|
|
|
0x03, 0x37, 0x80, 0x03, 0x39, 0xA0, 0x03, 0x3B, 0xC0, 0x03, 0x3D, 0xE0, 0x03, 0x3F, 0x00, 0x04,
|
|
|
|
|
0x41, 0x20, 0x04, 0x43, 0x40, 0x04, 0x45, 0x60, 0x04, 0x47, 0x80, 0x04, 0x49, 0xA0, 0x04, 0x4B,
|
|
|
|
|
0xC0, 0x04, 0x4D, 0xE0, 0x04, 0x4F, 0x00, 0x05, 0x51, 0x20, 0x05, 0x53, 0x40, 0x05, 0x55, 0x60,
|
|
|
|
|
0x05, 0x57, 0x80, 0x05, 0x59, 0xA0, 0x05, 0x5B, 0xC0, 0x05, 0x5D, 0xE0, 0x05, 0x5F, 0x00, 0x06,
|
|
|
|
|
0x61, 0x20, 0x06, 0x63, 0x40, 0x06, 0x65, 0x60, 0x06, 0x67, 0x80, 0x06, 0x69, 0xA0, 0x06, 0x6B,
|
|
|
|
|
0xC0, 0x06, 0x6D, 0xE0, 0x06, 0x6F, 0x00, 0x07, 0x71, 0x20, 0x07, 0x73, 0x40, 0x07, 0x75, 0x60,
|
|
|
|
|
0x07, 0x77, 0x80, 0x07, 0x79, 0xA0, 0x07, 0x7B, 0xC0, 0x07, 0x7D, 0xE0, 0x07, 0x7F, 0x00, 0x08,
|
|
|
|
|
0x81, 0x20, 0x08, 0x83, 0x40, 0x08, 0x85, 0x60, 0x08, 0x87, 0x80, 0x08, 0x89, 0xA0, 0x08, 0x8B,
|
|
|
|
|
0xC0, 0x08, 0x8D, 0xE0, 0x08, 0x8F, 0x00, 0x09, 0x91, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
};
|
|
|
|
|
#else
|
|
|
|
|
const char g_FAT[BLOCK_SIZE] =
|
|
|
|
|
{
|
|
|
|
|
0xF8, 0xFF, 0xFF, 0x03, 0x40, 0x00, 0x05, 0x60, 0x00, 0x07, 0x80, 0x00, 0x09, 0xF0, 0xFF, 0x0B,
|
|
|
|
|
0xC0, 0x00, 0x0D, 0xE0, 0x00, 0x0F, 0x00, 0x01, 0x11, 0x20, 0x01, 0x13, 0x40, 0x01, 0x15, 0x60,
|
|
|
|
|
0x01, 0x17, 0x80, 0x01, 0x19, 0xA0, 0x01, 0x1B, 0xC0, 0x01, 0x1D, 0xE0, 0x01, 0x1F, 0x00, 0x02,
|
|
|
|
|
0x21, 0x20, 0x02, 0x23, 0x40, 0x02, 0x25, 0x60, 0x02, 0x27, 0x80, 0x02, 0x29, 0xA0, 0x02, 0x2B,
|
|
|
|
|
0xC0, 0x02, 0x2D, 0xE0, 0x02, 0x2F, 0x00, 0x03, 0x31, 0x20, 0x03, 0x33, 0x40, 0x03, 0x35, 0x60,
|
|
|
|
|
0x03, 0x37, 0x80, 0x03, 0x39, 0xA0, 0x03, 0x3B, 0xC0, 0x03, 0x3D, 0xE0, 0x03, 0x3F, 0x00, 0x04,
|
|
|
|
|
0x41, 0x20, 0x04, 0x43, 0x40, 0x04, 0x45, 0x60, 0x04, 0x47, 0x80, 0x04, 0x49, 0xA0, 0x04, 0x4B,
|
|
|
|
|
0xC0, 0x04, 0x4D, 0xE0, 0x04, 0x4F, 0x00, 0x05, 0x51, 0x20, 0x05, 0x53, 0x40, 0x05, 0x55, 0x60,
|
|
|
|
|
0x05, 0x57, 0x80, 0x05, 0x59, 0xA0, 0x05, 0x5B, 0xC0, 0x05, 0x5D, 0xE0, 0x05, 0x5F, 0x00, 0x06,
|
|
|
|
|
0x61, 0x20, 0x06, 0x63, 0x40, 0x06, 0x65, 0x60, 0x06, 0x67, 0x80, 0x06, 0x69, 0xA0, 0x06, 0x6B,
|
|
|
|
|
0xC0, 0x06, 0x6D, 0xE0, 0x06, 0x6F, 0x00, 0x07, 0x71, 0x20, 0x07, 0x73, 0x40, 0x07, 0x75, 0x60,
|
|
|
|
|
0x07, 0x77, 0x80, 0x07, 0x79, 0xA0, 0x07, 0x7B, 0xC0, 0x07, 0x7D, 0xE0, 0x07, 0x7F, 0x00, 0x08,
|
|
|
|
|
0x81, 0x20, 0x08, 0x83, 0x40, 0x08, 0x85, 0x60, 0x08, 0x87, 0x80, 0x08, 0x89, 0xF0, 0xFF, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// File Attributes
|
|
|
|
|
// 0 0x01 Read Only.
|
|
|
|
@ -429,7 +378,7 @@ typedef struct
|
|
|
|
|
} FATDirEntry_t;
|
|
|
|
|
|
|
|
|
|
// First 16 FAT root directory entries (1 sector)
|
|
|
|
|
const FATDirEntry_t g_DIRroot[16] =
|
|
|
|
|
const FATDirEntry_t g_DIRroot[] =
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
{ USB_PRODUCT },
|
|
|
|
@ -447,9 +396,9 @@ const FATDirEntry_t g_DIRroot[16] =
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ 'E', 'E', 'P', 'R', 'O', 'M', ' ', ' '},
|
|
|
|
|
{ 'B', 'I', 'N'},
|
|
|
|
|
0x20, // Archive
|
|
|
|
|
{ 'F', 'I', 'R', 'M', 'W', 'A', 'R', 'E'},
|
|
|
|
|
{ 'T', 'X', 'T'},
|
|
|
|
|
0x21, // Readonly+Archive
|
|
|
|
|
0x00,
|
|
|
|
|
0x3E,
|
|
|
|
|
0xA301,
|
|
|
|
@ -459,7 +408,7 @@ const FATDirEntry_t g_DIRroot[16] =
|
|
|
|
|
0xA302,
|
|
|
|
|
0x3D55,
|
|
|
|
|
0x0002,
|
|
|
|
|
EEPROM_SIZE
|
|
|
|
|
sizeof(firmware_txt) + strlen(getOtherVersion())
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ 'F', 'I', 'R', 'M', 'W', 'A', 'R', 'E'},
|
|
|
|
@ -477,237 +426,122 @@ const FATDirEntry_t g_DIRroot[16] =
|
|
|
|
|
0x0000,
|
|
|
|
|
0xA302,
|
|
|
|
|
0x3D55,
|
|
|
|
|
0x0002 + (EEPROM_SIZE/BLOCK_SIZE)/8,
|
|
|
|
|
0x0003,
|
|
|
|
|
FLASHSIZE
|
|
|
|
|
},
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
{ 'E', 'E', 'P', 'R', 'O', 'M', ' ', ' '},
|
|
|
|
|
{ 'B', 'I', 'N'},
|
|
|
|
|
0x20, // Archive
|
|
|
|
|
0x00,
|
|
|
|
|
0x3E,
|
|
|
|
|
0xA301,
|
|
|
|
|
0x3D55,
|
|
|
|
|
0x3D55,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
{ '\x00', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
|
|
|
|
|
{ ' ', ' ', ' '},
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x0000,
|
|
|
|
|
0x00000000
|
|
|
|
|
0xA302,
|
|
|
|
|
0x3D55,
|
|
|
|
|
0x0003 + (FLASHSIZE/BLOCK_SIZE)/8,
|
|
|
|
|
EEPROM_SIZE
|
|
|
|
|
},
|
|
|
|
|
#endif
|
|
|
|
|
// Emty entries are 0x00, omitted here. Up to 16 entries can be defined here
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void writeByte(uint8_t *buffer, uint16_t sector, int byte, uint8_t value)
|
|
|
|
|
{
|
|
|
|
|
if (byte >= sector* BLOCK_SIZE && byte < (sector+1)* BLOCK_SIZE)
|
|
|
|
|
buffer[byte - sector*BLOCK_SIZE] = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void pushCluster(uint8_t *buffer, uint16_t sector, uint16_t & cluster, int & rest, uint16_t value)
|
|
|
|
|
{
|
|
|
|
|
// boot sector is in front of FAT
|
|
|
|
|
sector= sector-1;
|
|
|
|
|
|
|
|
|
|
// First byte of the cluster
|
|
|
|
|
int startbyte = cluster *3/2;
|
|
|
|
|
if (cluster % 2 == 0) {
|
|
|
|
|
// First 12 bit half
|
|
|
|
|
rest = value >> 8;
|
|
|
|
|
writeByte(buffer, sector, startbyte, value & 0xff);
|
|
|
|
|
} else {
|
|
|
|
|
// second 12 bit half, write rest and next byte
|
|
|
|
|
writeByte(buffer, sector, startbyte, value << 4 | rest );
|
|
|
|
|
writeByte(buffer, sector, startbyte+1, (value >> 4) & 0xff);
|
|
|
|
|
}
|
|
|
|
|
cluster++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// count is number of 512 byte sectors
|
|
|
|
|
int32_t fat12Read(uint8_t * buffer, uint16_t sector, uint16_t count)
|
|
|
|
|
{
|
|
|
|
|
while(count) {
|
|
|
|
|
memset(buffer, 0x00, BLOCK_SIZE);
|
|
|
|
|
if (sector == 0) {
|
|
|
|
|
memcpy(buffer, g_FATboot, BLOCK_SIZE ) ;
|
|
|
|
|
memcpy(buffer, g_FATboot, sizeof(g_FATboot) ) ;
|
|
|
|
|
}
|
|
|
|
|
else if (sector == 1/*Reserved sector count*/) {
|
|
|
|
|
// FAT table.
|
|
|
|
|
memcpy(buffer, g_FAT, BLOCK_SIZE);
|
|
|
|
|
else if (sector == 1 || sector == 2) {
|
|
|
|
|
// FAT table. Generate on the fly to save the 1024 byte flash space
|
|
|
|
|
uint16_t cluster=0;
|
|
|
|
|
int rest;
|
|
|
|
|
pushCluster (buffer, sector, cluster, rest, (uint16_t) 0xFF8);
|
|
|
|
|
pushCluster (buffer, sector, cluster, rest, (uint16_t) 0xFFF);
|
|
|
|
|
|
|
|
|
|
// Entry for firmware.txt, exactly one cluster
|
|
|
|
|
pushCluster (buffer, sector, cluster, rest, (uint16_t) 0xFFF);
|
|
|
|
|
|
|
|
|
|
// Entry for firmware.bin
|
|
|
|
|
for (int i=0;i<FLASHSIZE/BLOCK_SIZE/8 -1;i++)
|
|
|
|
|
pushCluster (buffer, sector, cluster, rest, cluster+1);
|
|
|
|
|
pushCluster (buffer, sector, cluster, rest, (uint16_t) 0xFFF);
|
|
|
|
|
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
// Entry for eeprom.bin
|
|
|
|
|
for (int i=0;i<EEPROM_SIZE/BLOCK_SIZE/8 -1;i++)
|
|
|
|
|
pushCluster (buffer, sector, cluster, rest, cluster+1);
|
|
|
|
|
pushCluster (buffer, sector, cluster, rest, (uint16_t) 0xFFF);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Ensure last cluster is written if it is the first half
|
|
|
|
|
pushCluster (buffer, sector, cluster, rest, (uint16_t) 0x000);
|
|
|
|
|
|
|
|
|
|
// Rest is 0x0 as per memset
|
|
|
|
|
}
|
|
|
|
|
else if (sector == 2) {
|
|
|
|
|
memcpy(buffer, g_DIRroot, BLOCK_SIZE ) ;
|
|
|
|
|
else if (sector == 3) {
|
|
|
|
|
memcpy(buffer, g_DIRroot, sizeof(g_DIRroot) ) ;
|
|
|
|
|
}
|
|
|
|
|
else if (sector < 3 + (EEPROM_SIZE/BLOCK_SIZE)) {
|
|
|
|
|
eepromReadBlock(buffer, (sector-3)*BLOCK_SIZE, BLOCK_SIZE);
|
|
|
|
|
else if (sector == 4)
|
|
|
|
|
{
|
|
|
|
|
memcpy(buffer, firmware_txt, sizeof(firmware_txt));
|
|
|
|
|
memcpy(buffer + sizeof(firmware_txt), getOtherVersion(), strlen(getOtherVersion()));
|
|
|
|
|
}
|
|
|
|
|
else if (sector < 3 + (EEPROM_SIZE/BLOCK_SIZE) + (FLASHSIZE/BLOCK_SIZE)) {
|
|
|
|
|
else if (sector < RESERVED_SECTORS)
|
|
|
|
|
{
|
|
|
|
|
// allocated to firmware.txt
|
|
|
|
|
}
|
|
|
|
|
else if (sector < RESERVED_SECTORS + (FLASHSIZE/BLOCK_SIZE )) {
|
|
|
|
|
uint32_t address;
|
|
|
|
|
address = sector - 3 - (EEPROM_SIZE/BLOCK_SIZE);
|
|
|
|
|
address = sector - RESERVED_SECTORS;
|
|
|
|
|
address *= BLOCK_SIZE;
|
|
|
|
|
address += FIRMWARE_ADDRESS;
|
|
|
|
|
memcpy(buffer, (uint8_t *)address, BLOCK_SIZE);
|
|
|
|
|
}
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
else if (sector < RESERVED_SECTORS + (EEPROM_SIZE/BLOCK_SIZE) + (FLASHSIZE/BLOCK_SIZE)) {
|
|
|
|
|
eepromReadBlock(buffer, (sector - RESERVED_SECTORS - (FLASHSIZE/BLOCK_SIZE))*BLOCK_SIZE, BLOCK_SIZE);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
buffer += BLOCK_SIZE ;
|
|
|
|
|
sector++ ;
|
|
|
|
|
count-- ;
|
|
|
|
|
}
|
|
|
|
|
return 0 ;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int32_t fat12Write(const uint8_t * buffer, uint16_t sector, uint16_t count)
|
|
|
|
|
{
|
|
|
|
|
enum FatWriteOperation {
|
|
|
|
@ -716,39 +550,21 @@ int32_t fat12Write(const uint8_t * buffer, uint16_t sector, uint16_t count)
|
|
|
|
|
FATWRITE_FIRMWARE
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static uint8_t operation = FATWRITE_NONE;
|
|
|
|
|
// Silence compiler warning that this is not used on X10
|
|
|
|
|
__attribute__((unused)) static uint8_t operation = FATWRITE_NONE;
|
|
|
|
|
|
|
|
|
|
TRACE("FAT12 Write(sector=%d, count=%d)", sector, count);
|
|
|
|
|
|
|
|
|
|
if (sector < 3) {
|
|
|
|
|
if (sector < RESERVED_SECTORS) {
|
|
|
|
|
// reserved, read-only
|
|
|
|
|
}
|
|
|
|
|
else if (sector < 3 + (EEPROM_SIZE/BLOCK_SIZE)) {
|
|
|
|
|
// eeprom
|
|
|
|
|
while (count) {
|
|
|
|
|
if (operation == FATWRITE_NONE && isEepromStart(buffer)) {
|
|
|
|
|
TRACE("EEPROM start found in sector %d", sector);
|
|
|
|
|
operation = FATWRITE_EEPROM;
|
|
|
|
|
}
|
|
|
|
|
if (operation == FATWRITE_EEPROM) {
|
|
|
|
|
eepromWriteBlock((uint8_t *)buffer, (sector-3)*BLOCK_SIZE, BLOCK_SIZE);
|
|
|
|
|
}
|
|
|
|
|
buffer += BLOCK_SIZE;
|
|
|
|
|
sector++;
|
|
|
|
|
count--;
|
|
|
|
|
if (sector-3 >= (EEPROM_SIZE/BLOCK_SIZE)) {
|
|
|
|
|
TRACE("EEPROM end written at sector %d", sector-1);
|
|
|
|
|
operation = FATWRITE_NONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (sector < 3 + (EEPROM_SIZE/BLOCK_SIZE) + (FLASHSIZE/BLOCK_SIZE)) {
|
|
|
|
|
else if (sector < RESERVED_SECTORS + (FLASHSIZE/BLOCK_SIZE)) {
|
|
|
|
|
#if !defined(BOOT) // Don't allow overwrite of running firmware
|
|
|
|
|
return -1;
|
|
|
|
|
#else
|
|
|
|
|
// firmware
|
|
|
|
|
uint32_t address;
|
|
|
|
|
address = sector - 3 - (EEPROM_SIZE/BLOCK_SIZE);
|
|
|
|
|
address = sector - RESERVED_SECTORS;
|
|
|
|
|
address *= BLOCK_SIZE;
|
|
|
|
|
address += FIRMWARE_ADDRESS;
|
|
|
|
|
while (count) {
|
|
|
|
@ -767,13 +583,33 @@ int32_t fat12Write(const uint8_t * buffer, uint16_t sector, uint16_t count)
|
|
|
|
|
}
|
|
|
|
|
sector++;
|
|
|
|
|
count--;
|
|
|
|
|
if (sector-3-(EEPROM_SIZE/BLOCK_SIZE) >= (FLASHSIZE/BLOCK_SIZE)) {
|
|
|
|
|
if (sector-RESERVED_SECTORS >= (FLASHSIZE/BLOCK_SIZE)) {
|
|
|
|
|
TRACE("FIRMWARE end written at sector %d", sector-1);
|
|
|
|
|
operation = FATWRITE_NONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#if defined(EEPROM)
|
|
|
|
|
else if (sector < RESERVED_SECTORS + (EEPROM_SIZE/BLOCK_SIZE) + (FLASHSIZE/BLOCK_SIZE)) {
|
|
|
|
|
// eeprom
|
|
|
|
|
while (count) {
|
|
|
|
|
if (operation == FATWRITE_NONE && isEepromStart(buffer)) {
|
|
|
|
|
TRACE("EEPROM start found in sector %d", sector);
|
|
|
|
|
operation = FATWRITE_EEPROM;
|
|
|
|
|
}
|
|
|
|
|
if (operation == FATWRITE_EEPROM) {
|
|
|
|
|
eepromWriteBlock((uint8_t *)buffer, (sector-RESERVED_SECTORS-(FLASHSIZE/BLOCK_SIZE))*BLOCK_SIZE, BLOCK_SIZE);
|
|
|
|
|
}
|
|
|
|
|
buffer += BLOCK_SIZE;
|
|
|
|
|
sector++;
|
|
|
|
|
count--;
|
|
|
|
|
if (sector-RESERVED_SECTORS >= (EEPROM_SIZE/BLOCK_SIZE)+(FLASHSIZE/BLOCK_SIZE)) {
|
|
|
|
|
TRACE("EEPROM end written at sector %d", sector-1);
|
|
|
|
|
operation = FATWRITE_NONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return 0 ;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|