Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMake/binutils.ESP32.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,12 @@ macro(nf_setup_target_build)
${Graphics_Sources}
)

# include storage operation support, if feature is enabled
if(NF_FEATURE_HAS_ACCESSIBLE_STORAGE)
target_sources(${NANOCLR_PROJECT_NAME}.elf PUBLIC
${CMAKE_SOURCE_DIR}/src/HAL/nanoHAL_StorageOperation.cpp)
endif()

nf_add_platform_sources(${NANOCLR_PROJECT_NAME})

# include directories for nanoCLR
Expand Down
6 changes: 6 additions & 0 deletions CMake/binutils.common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ macro(nf_add_common_sources)
${Graphics_Sources}
)

# include storage operation support, if feature is enabled
if(NF_FEATURE_HAS_ACCESSIBLE_STORAGE)
target_sources(${NFACS_TARGET}.elf PUBLIC
${CMAKE_SOURCE_DIR}/src/HAL/nanoHAL_StorageOperation.cpp)
endif()

endif()

endmacro()
Expand Down
2 changes: 1 addition & 1 deletion src/CLR/Debugger/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1388,7 +1388,7 @@ bool CLR_DBG_Debugger::Monitor_StorageOperation(WP_Message *message)
Monitor_StorageOperation_Command *cmd = (Monitor_StorageOperation_Command *)message->m_payload;
Monitor_StorageOperation_Reply cmdReply;

cmdReply.ErrorCode = HAL_StorageOperation(cmd->Operation, cmd->NameLength, cmd->DataLength, cmd->Offset, cmd->Data);
cmdReply.ErrorCode = HAL_StorageOperation(cmd->Operation, cmd->DataLength, cmd->Offset, cmd->Data);

WP_ReplyToCommand(message, true, false, &cmdReply, sizeof(cmdReply));

Expand Down
18 changes: 2 additions & 16 deletions src/CLR/Debugger/Debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#ifndef DEBUGGER_H
#define DEBUGGER_H

#include <nanoHAL_StorageOperation.h>

// enum with CLR debugging commands
// backwards compatible with .NETMF
typedef enum CLR_DBG_Commands_Debugging
Expand Down Expand Up @@ -102,20 +104,4 @@ typedef enum AccessMemoryErrorCodes

} AccessMemoryErrorCodes;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// !!! KEEP IN SYNC WITH nanoFramework.Tools.Debugger.WireProtocol.StorageOperationErrorCode (in managed code) !!! //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef enum StorageOperationErrorCode
{
// no error
NoError = 0x0001,
// write error
WriteError = 0x0010,
// delete error
DeleteError = 0x0020,
// platform error
PlatformError = 0x0030,

} StorageOperationErrorCode;

#endif // DEBUGGER_H
1 change: 0 additions & 1 deletion src/CLR/Include/WireProtocol_MonitorCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@ typedef struct __nfpack Monitor_UpdateConfiguration_Command
typedef struct Monitor_StorageOperation_Command
{
uint32_t Operation;
uint32_t NameLength;
uint32_t DataLength;
uint32_t Offset;
uint8_t Data[1];
Expand Down
23 changes: 17 additions & 6 deletions src/HAL/Include/nanoHAL_StorageOperation.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,28 @@

#include <nanoCLR_Headers.h>

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// !!! KEEP IN SYNC WITH nanoFramework.Tools.Debugger.WireProtocol.StorageOperationErrorCode (in managed code) !!! //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef enum StorageOperationErrorCode
{
// no error
NoError = 0x0001,
// write error
WriteError = 0x0010,
// delete error
DeleteError = 0x0020,
// platform error
PlatformError = 0x0030,

} StorageOperationErrorCode;

#ifdef __cplusplus
extern "C"
{
#endif

uint32_t HAL_StorageOperation(
uint8_t operation,
uint32_t nameLength,
uint32_t dataLength,
uint32_t offset,
uint8_t *data);
uint32_t HAL_StorageOperation(uint8_t operation, uint32_t dataLength, uint32_t offset, uint8_t *data);

#ifdef __cplusplus
}
Expand Down
161 changes: 161 additions & 0 deletions src/HAL/nanoHAL_StorageOperation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//

#include <nanoHAL.h>
#include <nanoHAL_v2.h>
#include <nanoWeak.h>
#include <nanoCLR_Runtime.h>
#include <nanoCLR_Types.h>
#include <nanoPAL_FileSystem.h>
#include <nanoCLR_FileStream.h>
#include <nanoHAL_StorageOperation.h>
#include <WireProtocol_MonitorCommands.h>

#if CONFIG_NF_FEATURE_HAS_ACCESSIBLE_STORAGE

uint32_t HAL_StorageOperation(uint8_t operation, uint32_t dataLength, uint32_t offset, uint8_t *data)
{
char *storageName = NULL;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
char *rootName = NULL;
char *relativePath = NULL;
uint8_t *fileData = NULL;
uint32_t rootNameLength = 0;
FileSystemVolume *volume = NULL;
StorageOperationErrorCode errorCode = StorageOperationErrorCode::NoError;

// point to the storage name in the data buffer
storageName = (char *)data;

// split the path into root name and relative path
if (FAILED(CLR_RT_FileStream::SplitFilePath(storageName, rootName, rootNameLength, relativePath)))
{
errorCode = StorageOperationErrorCode::PlatformError;
goto done;
}

// find the volume for this path
volume = FileSystemVolumeList::FindVolume(rootName, rootNameLength);

if (volume == NULL)
{
errorCode = StorageOperationErrorCode::PlatformError;
goto done;
}

// point to the file data in the data buffer (after the storage name and null terminator)
fileData = (uint8_t *)(data + hal_strlen_s(storageName) + 1);

if (operation == StorageOperation_Monitor::StorageOperation_Write)
{
void *fileHandle = NULL;
char dirPath[FS_MAX_DIRECTORY_LENGTH];
char *lastSeparator;
int bytesWritten = 0;

// extract parent directory from relative path and create it if needed
snprintf(dirPath, sizeof(dirPath), "%s", relativePath);

lastSeparator = strrchr(dirPath, '\\');
if (lastSeparator == NULL)
{
lastSeparator = strrchr(dirPath, '/');
}

if (lastSeparator != NULL && lastSeparator != dirPath)
{
*lastSeparator = '\0';

if (FAILED(volume->CreateDirectory(dirPath)))
{
errorCode = StorageOperationErrorCode::WriteError;
goto done;
}
}

// open the file (creates it, if it doesn't exist)
if (FAILED(volume->Open(relativePath, fileHandle)))
{
errorCode = StorageOperationErrorCode::WriteError;
goto done;
}

// write the data
if (FAILED(volume->Write(fileHandle, fileData, (int)dataLength, &bytesWritten)))
{
errorCode = StorageOperationErrorCode::WriteError;
volume->Close(fileHandle);
goto done;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// close file
volume->Close(fileHandle);

if ((uint32_t)bytesWritten != dataLength)
{
// failed to write expected number of bytes
errorCode = StorageOperationErrorCode::WriteError;
}
}
else if (operation == StorageOperation_Monitor::StorageOperation_Append)
{
void *fileHandle = NULL;
int64_t position;
int bytesWritten = 0;

// open the file
if (FAILED(volume->Open(relativePath, fileHandle)))
{
errorCode = StorageOperationErrorCode::WriteError;
goto done;
}

// seek to the end, to append
if (FAILED(volume->Seek(fileHandle, 0, SEEKORIGIN_END, &position)))
{
errorCode = StorageOperationErrorCode::WriteError;
volume->Close(fileHandle);
goto done;
}

// validate that the seek position matches the offset provided
if (position != offset)
{
errorCode = StorageOperationErrorCode::WriteError;
volume->Close(fileHandle);
goto done;
}

// append the data
if (FAILED(volume->Write(fileHandle, fileData, (int)dataLength, &bytesWritten)))
{
errorCode = StorageOperationErrorCode::WriteError;
volume->Close(fileHandle);
goto done;
}

// close file
volume->Close(fileHandle);

if ((uint32_t)bytesWritten != dataLength)
{
// failed to write expected number of bytes
errorCode = StorageOperationErrorCode::WriteError;
}
}
else if (operation == StorageOperation_Monitor::StorageOperation_Delete)
{
// remove the file
if (FAILED(volume->Delete(relativePath, false)))
{
errorCode = StorageOperationErrorCode::DeleteError;
}
}

done:

return errorCode;
}

#endif // CONFIG_NF_FEATURE_HAS_ACCESSIBLE_STORAGE
5 changes: 0 additions & 5 deletions targets/ChibiOS/_common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ if(NF_FEATURE_HAS_CONFIG_BLOCK)
list(APPEND TARGET_CHIBIOS_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_ConfigurationManager.cpp)
endif()

# include internal storage, if feature is enabled
if(NF_FEATURE_HAS_ACCESSIBLE_STORAGE)
list(APPEND TARGET_CHIBIOS_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_StorageOperation.cpp)
endif()

# append nanoHAL
list(APPEND TARGET_CHIBIOS_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/targetHAL.c)
list(APPEND TARGET_CHIBIOS_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/targetHAL_Time.cpp)
Expand Down
Loading
Loading