summaryrefslogtreecommitdiff
path: root/src/code/sFRm_flashrom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/code/sFRm_flashrom.c')
-rw-r--r--src/code/sFRm_flashrom.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/code/sFRm_flashrom.c b/src/code/sFRm_flashrom.c
new file mode 100644
index 0000000..589ba3d
--- /dev/null
+++ b/src/code/sFRm_flashrom.c
@@ -0,0 +1,209 @@
+#include "sFRm_flashrom.h"
+
+#include "libu64/stackcheck.h"
+#include "os_internal_flash.h"
+
+#include "macros.h"
+#include "m_thread.h"
+#include "stack.h"
+
+OSMesgQueue sFlashromMsgQueue;
+OSMesg sFlashromMsgBuf[1];
+OSIoMesg sFlashromIOMsg;
+
+STACK(sFlashromStack, 0x400);
+StackEntry sFlashromStackInfo;
+OSThread sFlashromThread;
+FlashromRequest sFlashromRequest;
+
+s32 sFlashromIsInit = FALSE;
+
+s32 sFRm_Init(void) {
+ s32 ret = TRUE;
+ u32 type;
+ u32 maker;
+
+ osFlashInit();
+ sFRm_InitRequest();
+ osCreateMesgQueue(&sFlashromMsgQueue, sFlashromMsgBuf, ARRAY_COUNT(sFlashromMsgBuf));
+ osFlashReadId(&type, &maker);
+
+ switch (maker) {
+ case FLASH_VERSION_MX_PROTO_A:
+ break;
+
+ case FLASH_VERSION_MX_A:
+ break;
+
+ case FLASH_VERSION_MX_C:
+ break;
+
+ case FLASH_VERSION_MX_B_AND_D:
+ break;
+
+ case FLASH_VERSION_MEI:
+ break;
+
+ default:
+ ret = FALSE;
+ break;
+ }
+
+ if (ret == TRUE) {
+ sFlashromIsInit = TRUE;
+ }
+
+ return ret;
+}
+
+s32 sFRm_IsInit(void) {
+ return sFlashromIsInit;
+}
+
+s32 sFRm_EraseSector(u32 pageNum) {
+ return osFlashSectorErase(pageNum);
+}
+
+s32 sFRm_EraseAll(void) {
+ return osFlashAllErase();
+}
+
+s32 sFRm_WritePage(void* addr, u32 pageNum) {
+ s32 ret = -1;
+ s32 err;
+
+ osWritebackDCache(addr, FLASH_BLOCK_SIZE);
+ err = osFlashWriteBuffer(&sFlashromIOMsg, OS_MESG_PRI_NORMAL, addr, &sFlashromMsgQueue);
+ osRecvMesg(&sFlashromMsgQueue, NULL, OS_MESG_BLOCK);
+
+ if ((err != -1) && (err == 0)) {
+ ret = osFlashWriteArray(pageNum);
+ }
+
+ return ret;
+}
+
+s32 sFRm_Write(void* addr, u32 pageNum, u32 pageCount) {
+ s32 ret;
+ s32 retries;
+ u32 i;
+
+ if ((pageNum % FLASH_BLOCK_SIZE) != 0) {
+ return 1;
+ }
+
+ osWritebackDCache(addr, pageCount * FLASH_BLOCK_SIZE);
+
+ retries = 3;
+ do {
+ ret = osFlashSectorErase(pageNum);
+ if (ret == -1) {
+ return ret;
+ }
+
+ for (i = 0; i < pageCount; i++) {
+ ret = osFlashWriteBuffer(&sFlashromIOMsg, OS_MESG_PRI_NORMAL, (u8*)addr + i * FLASH_BLOCK_SIZE,
+ &sFlashromMsgQueue);
+ osRecvMesg(&sFlashromMsgQueue, NULL, OS_MESG_BLOCK);
+ if (ret == -1) {
+ break;
+ }
+
+ ret = osFlashWriteArray(pageNum + i);
+ if (ret == -1) {
+ break;
+ }
+ }
+ retries--;
+ } while ((ret == -1) && (retries != 0));
+
+ return ret;
+}
+
+s32 sFRm_ReadPage(void* addr, u32 pageNum) {
+ s32 ret;
+
+ osInvalDCache(addr, FLASH_BLOCK_SIZE);
+ ret = osFlashReadArray(&sFlashromIOMsg, 0, pageNum, addr, 1, &sFlashromMsgQueue);
+ osRecvMesg(&sFlashromMsgQueue, NULL, OS_MESG_BLOCK);
+
+ return ret;
+}
+
+s32 sFRm_Read(void* addr, u32 pageNum, u32 pageCount) {
+ s32 ret;
+ OSIoMesg msg;
+
+ osInvalDCache(addr, pageCount * FLASH_BLOCK_SIZE);
+ ret = osFlashReadArray(&msg, OS_MESG_PRI_NORMAL, pageNum, addr, pageCount, &sFlashromMsgQueue);
+ osRecvMesg(&sFlashromMsgQueue, NULL, OS_MESG_BLOCK);
+ return ret;
+}
+
+void sFRm_InitRequest(void) {
+ FlashromRequest* req = &sFlashromRequest;
+
+ req->type = 0;
+}
+
+void sFRm_proc(void* arg) {
+ FlashromRequest* req = (FlashromRequest*)arg;
+
+ switch (req->type) {
+ case FLASHROM_REQUEST_WRITE:
+ req->response = sFRm_Write(req->addr, req->pageNum, req->pageCount);
+ osSendMesg(&req->queue, (OSMesg)req->response, OS_MESG_BLOCK);
+ break;
+
+ case FLASHROM_REQUEST_READ:
+ req->response = sFRm_Read(req->addr, req->pageNum, req->pageCount);
+ osSendMesg(&req->queue, (OSMesg)req->response, OS_MESG_BLOCK);
+ break;
+ }
+}
+
+void sFRm_WriteAsync(void* addr, u32 pageNum, u32 pageCount) {
+ FlashromRequest* req = &sFlashromRequest;
+
+ req->type = FLASHROM_REQUEST_WRITE;
+ req->addr = addr;
+ req->pageNum = pageNum;
+ req->pageCount = pageCount;
+
+ osCreateMesgQueue(&req->queue, req->msgBuf, ARRAY_COUNT(req->msgBuf));
+ StackCheck_Init(&sFlashromStackInfo, sFlashromStack, STACK_TOP(sFlashromStack), 0, 0x100, "sFRm_flashrom");
+ osCreateThread(&sFlashromThread, M_THREAD_ID_FLASHROM, sFRm_proc, &sFlashromRequest, STACK_TOP(sFlashromStack),
+ M_PRIORITY_FLASHROM);
+ osStartThread(&sFlashromThread);
+}
+
+s32 sFRm_IsBusy(void) {
+ FlashromRequest* req = &sFlashromRequest;
+
+ if (sFRm_IsInit() != 1) {
+ return -1;
+ }
+
+ return MQ_IS_FULL(&req->queue);
+}
+
+s32 sFRm_AwaitResult(void) {
+ FlashromRequest* req = &sFlashromRequest;
+
+ osRecvMesg(&req->queue, NULL, OS_MESG_BLOCK);
+ osDestroyThread(&sFlashromThread);
+ StackCheck_Check(&sFlashromStackInfo);
+ StackCheck_Cleanup(&sFlashromStackInfo);
+ return req->response;
+}
+
+void sFRm_WriteSync(void* addr, u32 pageNum, u32 pageCount) {
+ sFRm_WriteAsync(addr, pageNum, pageCount);
+ sFRm_AwaitResult();
+}
+
+s32 sFRm_GetResult(void) {
+ FlashromRequest* req = &sFlashromRequest;
+
+ return req->response;
+}