diff options
| author | louist103 <35883445+louist103@users.noreply.github.com> | 2023-05-29 20:39:14 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-29 20:39:14 -0400 |
| commit | 51cd9df591322c4541ca9697a4ce4a6acde1fad6 (patch) | |
| tree | d168a1f3bddd564b377fd2e749c92be496a4d1f2 /src/code/sys_flashrom.c | |
| parent | 4143097c5a6080a1ebbb3d328b85178ab13ab8e6 (diff) | |
sys_flashrom matched (#1251)
* done
* WIP
* Fix the rebase
* fix build
* re match
* Last thing before the PR
* PR fixes
* PR Fixes (tharo)
* fix
* format
* PR fixes (hensldm)
* oops
* MAGIC
* Fix BSS and rename FLASH_MAGIC
* PR Fixes (Engineer)
* remove from functions.h
Diffstat (limited to 'src/code/sys_flashrom.c')
| -rw-r--r-- | src/code/sys_flashrom.c | 287 |
1 files changed, 248 insertions, 39 deletions
diff --git a/src/code/sys_flashrom.c b/src/code/sys_flashrom.c index 0db0b8744..c2665741e 100644 --- a/src/code/sys_flashrom.c +++ b/src/code/sys_flashrom.c @@ -1,44 +1,253 @@ +#include "prevent_bss_reordering.h" #include "global.h" #include "stack.h" #include "stackcheck.h" #include "system_malloc.h" -// extern UNK_TYPE1 D_801FBE10; -// extern UNK_TYPE1 D_801FBE28; -// extern UNK_TYPE1 D_801FBE2C; -// extern UNK_TYPE4 D_801FBE30; -extern STACK(sSysFlashromStack, 0x1000); -extern StackEntry sSysFlashromStackInfo; -extern OSThread sSysFlashromThread; -extern s80185D40 D_801FD008; -extern OSMesg D_801FD034[1]; - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_801857C0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_801857D0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185864.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185908.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185968.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_801859F0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185A2C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185B1C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185BE4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185C24.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/SysFlashrom_ThreadEntry.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185DDC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185EC4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185F04.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_flashrom/func_80185F64.s") +OSMesgQueue sFlashromMesgQueue; +OSMesg sFlashromMesg[1]; +s32 sFlashromIsInit; +s32 sFlashromVendor; + +STACK(sSysFlashromStack, 0x1000); +StackEntry sSysFlashromStackInfo; +OSThread sSysFlashromThread; +FlashromRequest sFlashromRequest; +OSMesg sSysFlashromMsgBuf[1]; + +s32 SysFlashrom_IsInit(void) { + return sFlashromIsInit; +} + +const char* SysFlashrom_GetVendorStr(void) { + switch (sFlashromVendor) { + case FLASH_VERSION_MX_PROTO_A: + return "PROTO A"; + + case FLASH_VERSION_MX_A: + return "A"; + + case FLASH_VERSION_MX_C: + return "C"; + + case FLASH_VERSION_MEI: + return "D(NEW)"; + + case FLASH_VERSION_MX_B_AND_D: + return "B or D"; + + default: + return "UNKNOWN"; + } +} + +s32 SysFlashrom_CheckFlashType(void) { + u32 flashType; + u32 flashVendor; + + if (!SysFlashrom_IsInit()) { + return -1; + } + osFlashReadId(&flashType, &flashVendor); + sFlashromVendor = flashVendor; + if (flashType == FLASH_TYPE_MAGIC) { + if ((flashVendor == FLASH_VERSION_MX_PROTO_A) || (flashVendor == FLASH_VERSION_MX_A) || + (flashVendor == FLASH_VERSION_MX_C) || (flashVendor == FLASH_VERSION_MEI) || + (flashVendor == FLASH_VERSION_MX_B_AND_D)) { + return 0; + } else { + return -1; + } + } + return -1; +} + +s32 SysFlashrom_InitFlash(void) { + osCreateMesgQueue(&sFlashromMesgQueue, sFlashromMesg, ARRAY_COUNT(sFlashromMesg)); + osFlashInit(); + sFlashromIsInit = true; + if (SysFlashrom_CheckFlashType() != 0) { + sFlashromIsInit = false; + return -1; + } + return 0; +} + +s32 SysFlashrom_ReadData(void* addr, u32 pageNum, u32 pageCount) { + OSIoMesg msg; + + if (!SysFlashrom_IsInit()) { + return -1; + } + osInvalDCache(addr, pageCount * FLASH_PAGE_SIZE); + osFlashReadArray(&msg, OS_MESG_PRI_NORMAL, pageNum, addr, pageCount, &sFlashromMesgQueue); + osRecvMesg(&sFlashromMesgQueue, NULL, OS_MESG_BLOCK); + return 0; +} + +s32 SysFlashrom_EraseSector(u32 page) { + if (!SysFlashrom_IsInit()) { + return -1; + } + return osFlashSectorErase(page); +} + +s32 SysFlashrom_ExecWrite(void* addr, u32 pageNum, u32 pageCount) { + OSIoMesg msg; + s32 result; + u32 i; + + if (!SysFlashrom_IsInit()) { + return -1; + } + // Ensure the page is always aligned to a sector boundary. + if ((pageNum % FLASH_PAGE_SIZE) != 0) { + Fault_AddHungupAndCrash("../sys_flashrom.c", 275); + } + osWritebackDCache(addr, pageCount * FLASH_PAGE_SIZE); + for (i = 0; i < pageCount; i++) { + osFlashWriteBuffer(&msg, OS_MESG_PRI_NORMAL, (u8*)addr + i * FLASH_PAGE_SIZE, &sFlashromMesgQueue); + osRecvMesg(&sFlashromMesgQueue, NULL, OS_MESG_BLOCK); + result = osFlashWriteArray(i + pageNum); + if (result != 0) { + return result; + } + } + return 0; +} + +s32 SysFlashrom_AttemptWrite(void* addr, u32 pageNum, u32 pageCount) { + s32 result; + s32 i; + + if (!SysFlashrom_IsInit()) { + return -1; + } + osWritebackDCache(addr, pageCount * FLASH_PAGE_SIZE); + i = 0; +failRetry: + result = SysFlashrom_EraseSector(pageNum); + if (result != 0) { + if (i < 3) { + i++; + goto failRetry; + } + return result; + } + result = SysFlashrom_ExecWrite(addr, pageNum, pageCount); + if (result != 0) { + if (i < 3) { + i++; + goto failRetry; + } + return result; + } + return 0; +} + +// Flash bits can only by flipped with a write from 1 -> 0. Going from 0 -> 1 requires an erasure. +// This function will try to determine if any sectors need to be erased before writing saving erase cycles. +s32 SysFlashrom_NeedsToErase(void* data, void* addr, u32 pageCount) { + u32 size; + u32 i; + + for (i = 0; i < pageCount * FLASH_PAGE_SIZE; i += 4) { + if ((*(s32*)data & *(s32*)addr) != *(s32*)addr) { + return false; + } + } + return true; +} + +s32 SysFlashrom_WriteData(void* addr, u32 pageNum, u32 pageCount) { + void* data; + size_t size; + s32 ret; + + if (!SysFlashrom_IsInit()) { + return -1; + } + size = pageCount * FLASH_PAGE_SIZE; + data = SystemArena_Malloc(size); + if (data == NULL) { + ret = SysFlashrom_AttemptWrite(addr, pageNum, pageCount); + } else { + SysFlashrom_ReadData(data, pageNum, pageCount); + if (bcmp(data, addr, size) == 0) { + ret = 0; + } else { + // Will always erase the sector even if it wouldn't normally need to. + if (SysFlashrom_NeedsToErase(data, addr, pageCount)) { + ret = SysFlashrom_AttemptWrite(addr, pageNum, pageCount); + } else { + ret = SysFlashrom_AttemptWrite(addr, pageNum, pageCount); + } + if (ret == 0) { + SysFlashrom_ReadData(data, pageNum, pageCount); + if (bcmp(data, addr, size) == 0) { + ret = 0; + } else { + ret = -1; + } + } + } + SystemArena_Free(data); + } + return ret; +} + +void SysFlashrom_ThreadEntry(void* arg) { + FlashromRequest* req = (FlashromRequest*)arg; + + switch (req->requestType) { + case FLASHROM_REQUEST_WRITE: + req->response = SysFlashrom_WriteData(req->addr, req->pageNum, req->pageCount); + osSendMesg(&req->messageQueue, req->response, OS_MESG_BLOCK); + break; + + case FLASHROM_REQUEST_READ: + req->response = SysFlashrom_ReadData(req->addr, req->pageNum, req->pageCount); + osSendMesg(&req->messageQueue, req->response, OS_MESG_BLOCK); + break; + } +} + +void SysFlashrom_WriteDataAsync(u8* addr, u32 pageNum, u32 pageCount) { + FlashromRequest* req = &sFlashromRequest; + if (SysFlashrom_IsInit()) { + req->requestType = FLASHROM_REQUEST_WRITE; + req->addr = addr; + req->pageNum = pageNum; + req->pageCount = pageCount; + osCreateMesgQueue(&req->messageQueue, sSysFlashromMsgBuf, ARRAY_COUNT(sSysFlashromMsgBuf)); + StackCheck_Init(&sSysFlashromStackInfo, sSysFlashromStack, STACK_TOP(sSysFlashromStack), 0, 0x100, + "sys_flashrom"); + osCreateThread(&sSysFlashromThread, Z_THREAD_ID_FLASHROM, SysFlashrom_ThreadEntry, req, + STACK_TOP(sSysFlashromStack), Z_PRIORITY_FLASHROM); + osStartThread(&sSysFlashromThread); + } +} + +s32 SysFlashrom_IsBusy(void) { + OSMesgQueue* queue = &sFlashromRequest.messageQueue; + + if (!SysFlashrom_IsInit()) { + return -1; + } + return MQ_IS_FULL(queue); +} + +s32 SysFlashrom_AwaitResult(void) { + if (!SysFlashrom_IsInit()) { + return -1; + } + osRecvMesg(&sFlashromRequest.messageQueue, NULL, OS_MESG_BLOCK); + osDestroyThread(&sSysFlashromThread); + StackCheck_Cleanup(&sSysFlashromStackInfo); + return sFlashromRequest.response; +} + +void SysFlashrom_WriteDataSync(void* addr, u32 pageNum, u32 pageCount) { + SysFlashrom_WriteDataAsync(addr, pageNum, pageCount); + SysFlashrom_AwaitResult(); +} |
