fix sdcard buffer overflow, fix switch case, use of TLV index file for stories

This commit is contained in:
Anthony Rabine 2023-07-31 11:45:41 +02:00
parent 084af988cb
commit fea5bc9c17
12 changed files with 182 additions and 62 deletions

View file

@ -5,6 +5,7 @@
#include "filesystem.h"
#include "mini_qoi.h"
#include "serializers.h"
#ifdef OST_USE_FF_LIBRARY
#include "ff.h"
@ -27,6 +28,21 @@ static FIL File[2]; /* File object */
static DIR Dir; /* Directory object */
static FILINFO Finfo;
file_t file_open(const char *filename)
{
#ifdef OST_USE_FF_LIBRARY
file_t fil;
FRESULT fr = f_open(&fil, filename, FA_READ);
if (fr != FR_OK)
{
debug_printf("ERROR: f_open %d\n\r", (int)fr);
}
return fil;
#else
return fopen(filename, "r");
#endif
}
static FRESULT scan_files(
char *path /* Pointer to the working buffer with start path */
)
@ -82,20 +98,6 @@ void filesystem_mount()
scan_files("");
}
// Ouvre le fichier d'index d'histoires
// Le format est le suivant :
// - Fichier texte, avec fin de ligne \n
// - Une ligne par histoire
// - la ligne contient le nom du répertoire au format UUIDv4 (36 caractères ASCII avec 4 tirets '-')
// Exemple: d0ad13e4-06de-4e00-877c-d922fdd37d13
int is_multiple_of_37(int nombre)
{
int plusGrandMultiple = (nombre / 37) * 37;
return (nombre - plusGrandMultiple) == 0;
}
/*
// Loop in all directories
void disk_start()
@ -138,30 +140,55 @@ void disk_start()
}
*/
static file_t IndexFile;
static uint8_t IndexBuf[260];
static const char *IndexFileName = "index.ost";
#define TLV_ARRAY_TYPE 0xAB
#define TLV_OBJECT_TYPE 0xE7
#define TLV_STRING_TYPE 0x3D
bool filesystem_read_index_file(ost_context_t *ctx)
{
FILINFO fno;
FRESULT fr = f_stat("index.ost", &fno);
FRESULT fr = f_stat(IndexFileName, &fno);
ctx->number_of_stories = 0;
ctx->current_story = 0;
if (fr == FR_OK)
{
ctx->index_file_size = fno.fsize;
UINT br;
bool valid_file = false;
int size = fno.fsize;
// une ligne = 36 octets (UUID) + 1 octet (\n) = 37
// Déjà, la taille doit être multiple de 37
if (is_multiple_of_37(size) && (size > 0))
// Minimum size of TLV is type + length, so check if there is potential data
if (ctx->index_file_size > 3)
{
valid_file = true;
ctx->number_of_stories = size / 37;
debug_printf("SUCCESS: found %d stories\r\n", ctx->number_of_stories);
FRESULT fr = f_open(&IndexFile, IndexFileName, FA_READ);
if (fr == FR_OK)
{
fr = f_read(&IndexFile, IndexBuf, 3, &br);
if (fr == FR_OK)
{
if ((br == 3) && (IndexBuf[0] = TLV_ARRAY_TYPE)) // Must be an array
{
// nomber of stories
ctx->number_of_stories = leu16_get(&IndexBuf[1]);
ctx->rd = 3;
debug_printf("SUCCESS: found %d stories\r\n", ctx->number_of_stories);
}
}
}
}
else
{
debug_printf("ERROR: index.ost not found\r\n");
}
}
else
{
debug_printf("ERROR: index.ost not found\r\n");
}
}
@ -172,21 +199,6 @@ static uint8_t bmpImage[256];
static color_t line[320];
file_t file_open(const char *filename)
{
#ifdef OST_USE_FF_LIBRARY
file_t fil;
FRESULT fr = f_open(&fil, filename, FA_READ);
if (fr != FR_OK)
{
debug_printf("ERROR: f_open %d\n\r", (int)fr);
}
return fil;
#else
return fopen(filename, "r");
#endif
}
void filesystem_display_image(const char *filename)
{
file_t fil;

View file

@ -2,12 +2,7 @@
#define FILESYSTEM_H
#include <stdbool.h>
typedef struct
{
uint32_t number_of_stories;
uint32_t current_story;
} ost_context_t;
#include "system.h"
bool filesystem_read_index_file(ost_context_t *ctx);
void filesystem_mount();

View file

@ -133,25 +133,25 @@ void FsTask(void *args)
{
switch (FsState)
{
FS_PLAY_SOUND:
case FS_PLAY_SOUND:
play_sound_file(fs_ev->filename);
FsState = FS_WAIT_FOR_EVENT;
break;
FS_DISPLAY_IMAGE:
case FS_DISPLAY_IMAGE:
filesystem_display_image(fs_ev->filename);
FsState = FS_WAIT_FOR_EVENT;
break;
FS_LOAD_INDEX:
case FS_LOAD_INDEX:
filesystem_read_index_file(&OstContext);
FsState = FS_WAIT_FOR_EVENT;
break;
FS_LOAD_STORY:
case FS_LOAD_STORY:
filesystem_load_rom(fs_ev->mem, fs_ev->filename);
// ROM loaded, execute story
FsState = FS_WAIT_FOR_EVENT;
break;
FS_WAIT_FOR_EVENT:
case FS_WAIT_FOR_EVENT:
default:
res = qor_mbox_wait(&FsMailBox, (void **)&fs_ev, 1000);
if (res == QOR_MBOX_OK)

View file

@ -1,5 +1,7 @@
#ifndef FS_TASK_H
#define FS_TASK_H
void fs_task_scan_index();
void fs_task_initialize();
#endif // FS_TASK_H

View file

@ -31,6 +31,13 @@ typedef struct
uint8_t ev;
} ost_hmi_event_t;
typedef enum
{
OST_SYS_WAIT_INDEX,
OST_SYS_PLAY_STORY_TITLE,
OST_SYS_WAIT_USER_EVENT
} ost_system_state_t;
// ===========================================================================================================
// GLOBAL STORY VARIABLES
// ===========================================================================================================
@ -44,6 +51,10 @@ static ost_hmi_event_t HmiEvent;
static ost_hmi_event_t HmiQueue[10];
static ost_system_state_t OstState = OST_SYS_WAIT_INDEX;
static ost_context_t OstContext;
// ===========================================================================================================
// HMI TASK (user interface, buttons manager, LCD)
// ===========================================================================================================
@ -55,6 +66,7 @@ void HmiTask(void *args)
// filesystem_display_image("/ba869e4b-03d6-4249-9202-85b4cec767a7/images/bird.qoi");
// Start by scanning the index file
fs_task_scan_index();
while (1)
{
@ -62,6 +74,18 @@ void HmiTask(void *args)
if (res == QOR_MBOX_OK)
{
switch (OstState)
{
case OST_SYS_PLAY_STORY_TITLE:
break;
case OST_SYS_WAIT_USER_EVENT:
break;
case OST_SYS_WAIT_INDEX:
default:
break;
}
}
else
{
@ -70,8 +94,19 @@ void HmiTask(void *args)
}
}
void hmi_task_ost_ready(uint32_t number_of_stories)
{
static ost_hmi_event_t OsReadyEv = {
.ev = OST_SYS_PLAY_STORY_TITLE};
OstContext.number_of_stories = number_of_stories;
OstContext.current_story = 0;
qor_mbox_notify(&HmiMailBox, (void **)&OsReadyEv, QOR_MBOX_OPTION_SEND_BACK);
}
void hmi_task_initialize()
{
OstState = OST_SYS_WAIT_INDEX;
qor_mbox_init(&HmiMailBox, (void **)&HmiQueue, 10);
qor_create_thread(&HmiTcb, HmiTask, HmiStack, sizeof(HmiStack) / sizeof(HmiStack[0]), HMI_TASK_PRIORITY, "HmiTask"); // less priority is the HMI (user inputs and LCD)

View file

@ -1,6 +1,10 @@
#ifndef HMI_TASK_H
#define HMI_TASK_H
#include <stdint.h>
void hmi_task_initialize();
void hmi_task_ost_ready(uint32_t number_of_stories);
#endif // HMI_TASK_H

View file

@ -102,7 +102,7 @@ qor_switch_context:
msr psp, r0 @ new task stack top address
str r0, [r1] @ Save the new top of stack
// str r0, [r1] @ Save the new top of stack
subs r0, r0, #32
ldmia r0!, {r4-r7}

View file

@ -304,7 +304,7 @@ static SD_Error SD_ReceiveData(uint8_t *data, uint16_t len)
/* receive the rest of data... */
// for (i = 1; i < len; ++i)
// data[i] = SD_SpiWriteByte(0xFF);
ost_hal_sdcard_spi_read(&data[1], len);
ost_hal_sdcard_spi_read(&data[1], (len - 1));
/* get CRC bytes (not really needed by us, but required by SD) */
SD_SpiWriteByte(0xFF);

View file

@ -1,9 +1,20 @@
#ifndef SYSTEM_H
#define SYSTEM_H
#include <stdint.h>
// On regroupe ici au les priorités des différents threads afin d'avoir une vision plus large
#define HMI_TASK_PRIORITY 1
#define VM_TASK_PRIORITY 2
#define FS_TASK_PRIORITY 3 ///< High priority for audio / file system access
typedef struct
{
uint32_t number_of_stories;
uint32_t current_story;
uint32_t index_file_size;
uint32_t rd; ///!< Read index in the Index file
} ost_context_t;
#endif // SYSTEM_H

View file

@ -2,6 +2,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "ost_hal.h"
#include "debug.h"

View file

@ -27,7 +27,12 @@ ResourcesDock::ResourcesDock(StoryProject &project, ResourceModel &model)
std::filesystem::copy(p, p2, std::filesystem::copy_options::overwrite_existing);
Resource res;
res.format = "BMP";
std::string ext = p.extension();
ext.erase(ext.begin()); // remove '.' dot sign
std::transform(ext.begin(), ext.end(), ext.begin(), ::toupper);
res.format = ext;
res.type = "image";
res.file = p.filename().generic_string();
m_resourcesModel.Append(res);
@ -38,7 +43,7 @@ ResourcesDock::ResourcesDock(StoryProject &project, ResourceModel &model)
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
".",
tr("Sound files (*.wav *.mp3 *.m4a)"));
tr("Sound files (*.wav *.mp3)"));
if (std::filesystem::exists(fileName.toStdString()))
{
@ -47,7 +52,12 @@ ResourcesDock::ResourcesDock(StoryProject &project, ResourceModel &model)
std::filesystem::copy(p, p2, std::filesystem::copy_options::overwrite_existing);
Resource res;
res.format = "WAV";
std::string ext = p.extension();
ext.erase(ext.begin()); // remove '.' dot sign
std::transform(ext.begin(), ext.end(), ext.begin(), ::toupper);
res.format = ext;
res.type = "sound";
res.file = p.filename().generic_string();
m_resourcesModel.Append(res);

View file

@ -12,18 +12,68 @@ void StoryProject::New(const std::string &uuid, const std::string &file_path)
Initialize(file_path);
}
#define TLV_ARRAY_TYPE 0xAB
#define TLV_OBJECT_TYPE 0xE7
#define TLV_STRING_TYPE 0x3D
class Tlv
{
public:
explicit Tlv(const std::string &filename)
{
m_file = std::ofstream(filename, std::ios::out | std::ios::binary);
}
~Tlv() {
m_file.close();
}
void add_array(uint16_t size)
{
m_file.write(reinterpret_cast<const char*>(&m_objectType), sizeof(m_objectType));
m_file.write(reinterpret_cast<const char*>(&size), sizeof(size));
}
void add_string(const char *s, uint16_t size)
{
m_file.write(reinterpret_cast<const char*>(&m_stringType), sizeof(m_stringType));
m_file.write(reinterpret_cast<const char*>(&size), sizeof(size));
m_file.write(s, size);
}
void add_object(uint16_t entries)
{
m_file.write(reinterpret_cast<const char*>(&m_arrayType), sizeof(m_arrayType));
m_file.write(reinterpret_cast<const char*>(&entries), sizeof(entries));
}
private:
std::ofstream m_file;
uint8_t m_arrayType = TLV_ARRAY_TYPE;
uint8_t m_objectType = TLV_OBJECT_TYPE;
uint8_t m_stringType = TLV_STRING_TYPE;
};
void StoryProject::SaveStory(const std::vector<uint8_t> &m_program)
{
std::ofstream o(m_working_dir + std::filesystem::path::preferred_separator + "story.c32", std::ios::out | std::ios::binary);
o.write(reinterpret_cast<const char*>(m_program.data()), m_program.size());
o.close();
// Generate title files
std::ofstream index(m_working_dir + std::filesystem::path::preferred_separator + "index.ost");
index << "/" << m_uuid << "/images/" << m_titleImage << "\n";
index << "/" << m_uuid << "/sounds/" << m_titleSound << "\n";
index.close();
Tlv tlv(m_working_dir + std::filesystem::path::preferred_separator + "index.ost");
tlv.add_array(1);
tlv.add_object(3);
tlv.add_string(m_uuid.c_str(), m_uuid.size()); // uuid
tlv.add_string(m_titleImage.c_str(), m_titleImage.size()); // title image
tlv.add_string(m_titleSound.c_str(), m_titleSound.size()); // title sound
}
void StoryProject::Initialize(const std::string &file_path)