BOOL SimpleStorage::Compact() { GLOBAL_LOCK(irq); BlockStorageStream* pFreeBlock = (s_pCurrentStream == &s_BsStreamA) ? &s_BsStreamB : &s_BsStreamA; SIMPLESTORAGE_FILE_HEADER header; UINT8 buffer[256]; const UINT32 eraseBlock = 0x0; const UINT32 activeBlock = SIMPLESTORAGE_ACTIVE_BLOCK_MARKER; pFreeBlock->Seek(0, BlockStorageStream::SeekBegin); if(!pFreeBlock->Erase(pFreeBlock->Length)) return FALSE; pFreeBlock->Seek(sizeof(SIMPLESTORAGE_BLOCK_HEADER), BlockStorageStream::SeekBegin); s_pCurrentStream->Seek(sizeof(SIMPLESTORAGE_BLOCK_HEADER), BlockStorageStream::SeekBegin); do { INT32 len; if(!ReadToNextFile(header)) break; if(header.Signature != SIMPLESTORAGE_FILE_SIGNATURE) break; pFreeBlock->Write((UINT8*)&header, sizeof(header)); len = header.Length; while(len > 0) { int bufLen = len < ARRAYSIZE(buffer) ? len : ARRAYSIZE(buffer); if(!s_pCurrentStream->ReadIntoBuffer((UINT8*)buffer, bufLen)) break; if(!pFreeBlock->Write((UINT8*)buffer, bufLen)) break; len -= bufLen; } } while(s_pCurrentStream->CurrentIndex + sizeof(header) < s_pCurrentStream->Length); s_pCurrentStream->Seek(0, BlockStorageStream::SeekBegin); s_pCurrentStream->Write((UINT8*)&eraseBlock, sizeof(eraseBlock)); pFreeBlock->Seek(0, BlockStorageStream::SeekBegin); pFreeBlock->Write((UINT8*)&activeBlock, sizeof(activeBlock)); s_pCurrentStream = pFreeBlock; return TRUE; }
UINT32 MicroBooter_PrepareForExecution(UINT32 physicalEntryPointAddress) { if (physicalEntryPointAddress == CODE_BASEADDRESS) { BlockStorageDevice *device; ByteAddress ByteAddress; UINT32 physicalAddress = CODE_BASEADDRESS; if (BlockStorageList::FindDeviceForPhysicalAddress( &device, physicalAddress, ByteAddress)) { BlockStorageStream stream; if(stream.Initialize(BlockUsage::CODE, device)) { BYTE *dst; if(stream.CurrentAddress() != CODE_BASEADDRESS) { hal_fprintf( STREAM_LCD, "Warn: at wrong offset: 0x%08x\r\n", (UINT32)stream.CurrentAddress()); debug_printf( "Warn: at wrong offset: 0x%08x\r\n", (UINT32)stream.CurrentAddress()); stream.Seek(CODE_BASEADDRESS - stream.CurrentAddress(), BlockStorageStream::SeekCurrent); } // load ER_FLASH only dst =(BYTE *) EXCODE_BASEADDRESS ; stream.Read( &dst, CODE_SIZE ); CPU_DrainWriteBuffers(); } } } return EXCODE_BASEADDRESS; }
void Initialize() { #if defined(PLATFORM_ARM_MOTE2) if (COM_IsUsb(HalSystemConfig.DebugTextPort)) WaitInterval = 5000; // The USB port must be selected and the Start button pressed all during this time else WaitInterval = 2000; // The USART port may be selected before powering on the Imote2, so it takes less time #else WaitInterval = 2000; #endif SerialPortActive = FALSE; UsartPort = USART_DEFAULT_PORT; UsingUsb = FALSE; UsbPort = USB1; UsbEventCode = USB_DEBUG_EVENT_IN; //--// // wait an extra second for buttons and COM port to stabilize Events_WaitForEvents( 0, 1000 ); // COM init is now delayed for TinyBootloader, so we need to initialize it here CPU_InitializeCommunication(); //--// // set default baud rate if(UsartPort != DEBUG_TEXT_PORT) { DebuggerPort_Initialize( UsartPort ); } // extra time to allow USB setup, so that we can see the printf Events_WaitForEvents( 0, 1000 ); hal_printf( "PortBooter v%d.%d.%d.%d\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION); hal_printf( "Build Date: %s %s\r\n", __DATE__, __TIME__); #if defined(__GNUC__) hal_printf( "GNU Compiler version %d\r\n", __GNUC__); #elif defined(__ADSPBLACKFIN__) hal_printf( "Blackfin Compiler version %d\r\n", __VERSIONNUM__ ); #else hal_printf( "ARM Compiler version %d\r\n", __ARMCC_VERSION); #endif //--// BlockStorageStream stream; FLASH_WORD ProgramWordCheck; if(!stream.Initialize(BlockUsage::CODE)) return; do { do { UINT32 addr = stream.CurrentAddress(); FLASH_WORD *pWord = &ProgramWordCheck; stream.Read( (BYTE**)&pWord, sizeof(FLASH_WORD) ); if(*pWord == PROGRAM_WORD_CHECK) { hal_printf("*** nXIP Program found at 0x%08x\r\n", addr ); Programs[ProgramCount++] = (UINT32)addr; } if(ProgramCount == MAX_PROGRAMS) break; } while( stream.Seek( BlockStorageStream::STREAM_SEEK_NEXT_BLOCK, BlockStorageStream::SeekCurrent ) ); } while(stream.NextStream()); }
BOOL MicroBooterUpdateProvider::InstallUpdate( MFUpdate* pUpdate, UINT8* pValidation, INT32 validationLen ) { if(pUpdate->Providers->Storage == NULL) return FALSE; if(!pUpdate->IsValidated()) return FALSE; switch(pUpdate->Header.UpdateType) { case MFUPDATE_UPDATETYPE_FIRMWARE: { HAL_UPDATE_CONFIG cfg; if(sizeof(cfg.UpdateSignature) < validationLen) return FALSE; cfg.Header.Enable = TRUE; cfg.UpdateID = pUpdate->Header.UpdateID; if(validationLen == sizeof(UINT32)) { cfg.UpdateSignType = HAL_UPDATE_CONFIG_SIGN_TYPE__CRC; } else { cfg.UpdateSignType = HAL_UPDATE_CONFIG_SIGN_TYPE__SIGNATURE; } memcpy( cfg.UpdateSignature, pValidation, validationLen ); if(HAL_CONFIG_BLOCK::UpdateBlockWithName(cfg.GetDriverName(), &cfg, sizeof(cfg), FALSE)) { CPU_Reset(); } } break; case MFUPDATE_UPDATETYPE_ASSEMBLY: { BlockStorageStream stream; if(NULL == BlockStorageList::GetFirstDevice()) { BlockStorageList::Initialize(); BlockStorage_AddDevices(); BlockStorageList::InitializeDevices(); } if(stream.Initialize(BlockUsage::DEPLOYMENT)) { if(pUpdate->Header.UpdateSubType == MFUPDATE_UPDATESUBTYPE_ASSEMBLY_REPLACE_DEPLOY) { do { stream.Erase(stream.Length); } while(stream.NextStream()); stream.Initialize(BlockUsage::DEPLOYMENT); } do { UINT8 buf[512]; INT32 offset = 0; INT32 len = sizeof(buf); const BlockDeviceInfo* deviceInfo = stream.Device->GetDeviceInfo(); BOOL isXIP = deviceInfo->Attribute.SupportsXIP; const CLR_RECORD_ASSEMBLY* header; INT32 headerInBytes = sizeof(CLR_RECORD_ASSEMBLY); BYTE * headerBuffer = NULL; if(!isXIP) { headerBuffer = (BYTE*)private_malloc( headerInBytes ); if(!headerBuffer) return FALSE; memset( headerBuffer, 0, headerInBytes ); } while(TRUE) { if(!stream.Read( &headerBuffer, headerInBytes )) break; header = (const CLR_RECORD_ASSEMBLY*)headerBuffer; // check header first before read if(!header->GoodHeader()) { stream.Seek(-headerInBytes); if(stream.IsErased(pUpdate->Header.UpdateSize)) { while(offset < pUpdate->Header.UpdateSize) { if((pUpdate->Header.UpdateSize - offset) < len) { len = pUpdate->Header.UpdateSize - offset; } offset += pUpdate->Providers->Storage->Read(pUpdate->StorageHandle, offset, buf, len); stream.Write(buf, len); } ClrReboot(); return TRUE; } break; } UINT32 AssemblySizeInByte = ROUNDTOMULTIPLE(header->TotalSize(), CLR_UINT32); stream.Seek( AssemblySizeInByte ); } if(!isXIP) private_free( headerBuffer ); } while(stream.NextStream()); } } break; } return FALSE; }
//////////////////////////////////////////////////////////////////////////////// // The TinyBooter_OnStateChange method is an event handler for state changes in // the TinyBooter. It is designed to help porting kit users control the tinybooter // execution and allow them to add diagnostics. //////////////////////////////////////////////////////////////////////////////// void TinyBooter_OnStateChange(TinyBooterState state, void* data, void ** retData) { switch (state) { //////////////////////////////////////////////////////////////////////////////////// // State_EnterBooterMode - TinyBooter has entered upload mode //////////////////////////////////////////////////////////////////////////////////// case State_EnterBooterMode: hal_fprintf(STREAM_LCD, "Waiting\r"); break; //////////////////////////////////////////////////////////////////////////////////// // State_ButtonPress - A button was pressed while Tinybooter // The data parameter is a pointer to the timeout value for the booter mode. //////////////////////////////////////////////////////////////////////////////////// case State_ButtonPress: if (NULL != data) { UINT32 down, up; INT32* timeout_ms = (INT32*)data; // wait forever if a button was pressed *timeout_ms = -1; // process buttons while (Buttons_GetNextStateChange(down, up)) { // leave a way to exit boot mode incase it was accidentally entered if (0 != (down & BUTTON_ENTR)) { // force an enumerate and launch *timeout_ms = 0; } } } break; //////////////////////////////////////////////////////////////////////////////////// // State_ValidCommunication - TinyBooter has received valid communication from the host // The data parameter is a pointer to the timeout value for the booter mode. //////////////////////////////////////////////////////////////////////////////////// case State_ValidCommunication: if (NULL != data) { INT32* timeout_ms = (INT32*)data; // if we received any com/usb data then let's change the timeout to at least 20 seconds if (*timeout_ms != -1 && *timeout_ms < 20000) { *timeout_ms = 20000; } } break; //////////////////////////////////////////////////////////////////////////////////// // State_Timeout - The default timeout for TinyBooter has expired and TinyBooter will // perform an EnumerateAndLaunch //////////////////////////////////////////////////////////////////////////////////// case State_Timeout: break; //////////////////////////////////////////////////////////////////////////////////// // State_MemoryXXX - Identifies memory accesses. //////////////////////////////////////////////////////////////////////////////////// case State_MemoryWrite: hal_fprintf(STREAM_LCD, "Wr: 0x%08x\r", (UINT32)data); break; case State_MemoryErase: hal_fprintf(STREAM_LCD, "Er: 0x%08x\r", (UINT32)data); break; //////////////////////////////////////////////////////////////////////////////////// // State_CryptoXXX - Start and result of Crypto signature check //////////////////////////////////////////////////////////////////////////////////// case State_CryptoStart: hal_fprintf(STREAM_LCD, "Chk signature \r"); hal_printf("Chk signature \r"); break; // The data parameter is a boolean that represents signature PASS/FAILURE case State_CryptoResult: if ((bool)data) { hal_fprintf(STREAM_LCD, "Signature PASS\r\n\r\n"); hal_printf("Signature PASS\r\n\r\n"); } else { hal_fprintf(STREAM_LCD, "Signature FAIL\r\n\r\n"); hal_printf("Signature FAIL\r\n\r\n"); } DebuggerPort_Flush(HalSystemConfig.DebugTextPort); break; //////////////////////////////////////////////////////////////////////////////////// // State_Launch - The host has requested to launch an application at a given address, // or a timeout has occured and TinyBooter is about to launch the // first application it finds in FLASH. // // The data parameter is a UINT32 value representing the launch address //////////////////////////////////////////////////////////////////////////////////// case State_Launch: UINT32 address = (UINT32)data; if (NULL != data) { hal_fprintf(STREAM_LCD, "Starting application at 0x%08x\r\n", address); debug_printf("Starting application at 0x%08x\r\n", address); if (address == CODE_BASEADDRESS || address == EXCODE_BASEADDRESS) { BlockStorageDevice *device; ByteAddress ByteAddress; UINT32 physicalAddress = CODE_BASEADDRESS; if (BlockStorageList::FindDeviceForPhysicalAddress(&device, physicalAddress, ByteAddress)) { BlockStorageStream stream; if (stream.Initialize(BlockUsage::CODE, device)) { if (stream.CurrentAddress() != CODE_BASEADDRESS) { hal_fprintf(STREAM_LCD, "Warn: at wrong offset: 0x%08x\r\n", (UINT32)stream.CurrentAddress()); debug_printf("Warn: at wrong offset: 0x%08x\r\n", (UINT32)stream.CurrentAddress()); stream.Seek(CODE_BASEADDRESS - stream.CurrentAddress(), BlockStorageStream::SeekCurrent); } BYTE *dst; dst = (BYTE *)EXCODE_BASEADDRESS; stream.Read(&dst, CODE_SIZE); if (retData != NULL) { *retData = (void*)EXCODE_BASEADDRESS; } CPU_DrainWriteBuffers(); } } } else if (retData != NULL) { *retData = (void*)data; } } break; } }