<commit_before>//
// Copyright (c) .NET Foundation and Contributors
// Portions Copyright (c) Microsoft Corporation.  All rights reserved.
// See LICENSE file in the project root for full license information.
//

#ifndef NANOPAL_BLOCKSTORAGE_H
#define NANOPAL_BLOCKSTORAGE_H

#include <nanoHAL_v2.h>
#include <target_BlockStorage.h>

/////////////////////////////////////////////////////////
// Description:
//   Definitions for the Block Storage device interface
//   for the nanoFramework
//
// Terminology:
//  Block Storage Device - device that stores data addressable
//                         as a chunk as opposed to byte or unsigned short level
//
//  Sector - smallest unit of storage for a Block device. Data is
//           read or written as a complete sector(unless the device
//           supports XIP which allows byte addresssing and reading
//           directly from the processor memory bus)
//
//  Block  - smallest eraseable unit of the storage device. A block
//           contains one or more sectors that are erased as a whole.
//           All sectors within a block are always the same size.
//
//  Region - Group of adjacent blocks that all contain sectors of the
//           same size.
//
//  Execute-In-Place (XIP) - Attribute of some storage types, NOR, ROM,
//          RAM, that allows direct execution of code from the device.
//          XIP capable devices are at least read-only and byte addresable
//          on the CPU memory bus.
//

// In flash media the distinction between a block and a sector is important
// so we define the sector address to make it clear.
typedef unsigned int ByteAddress;
typedef unsigned int SectorAddress;

//////////////////////////////////////////////////////////
// Description:
//   Flags to Indicate the status of a particular block in
//   flash. ALL sectors for a block *MUST* share the same
//   status.
//
// Remarks:
//   When the block is reserved the lower 16 bits specifies a
//   USAGE_XXXX value to indicate the purpose of the block.
//
//   The BlockRange information is technically dynamic in the
//   sense that it is not fixed or defined in hardware. Rather,
//   it is defined by the system designer. However, the BlockRange
//   info does not and *MUST* not change at run-time.  The only
//   exceptions to this rule is in the boot loader where the
//   storage device is being formated or re-laid out as part
//   of an update etc... and when an FS discovers a bad block
//   it should mark it as bad. WIthout this restriction
//   implementing an FS is virtually impossible since the FS
//   would have to deal with the possibility that the usage for
//   a Block could change at any point in time.
//
typedef enum BlockUsage
{
    BlockUsage_BOOTSTRAP = 0x0010,
    BlockUsage_CODE = 0x0020,
    BlockUsage_CONFIG = 0x0030,
    BlockUsage_FILESYSTEM = 0x0040,

    BlockUsage_DEPLOYMENT = 0x0050,

    BlockUsage_UPDATE = 0x0060,

    BlockUsage_SIMPLE_A = 0x0090,
    BlockUsage_SIMPLE_B = 0x00A0,

    BlockUsage_STORAGE_A = 0x00E0,
    BlockUsage_STORAGE_B = 0x00F0,

    BlockUsage_ANY = 0x0000,

} BlockUsage;

// upper 4 bits of USAGE_XXXX identifies the base type of info stored in the block
// using these values it is possible to scan a device for all managed code or all
// native code without worrying about the finer details of what it's for.

// Block contains XIP system native code
#define BlockRange_DATATYPE_NATIVECODE ((unsigned int)0x1000)
// Block contains managed code assemblies
#define BlockRange_DATATYPE_MANAGEDCODE ((unsigned int)0x2000)
// Block contains raw data
#define BlockRange_DATATYPE_RAW ((unsigned int)0x4000)

// use to mark the block is used for special purpose
#define BlockRange_ATTRIB_PRIMARY ((unsigned int)0x10000)

#define BlockRange_EXECUTABLE ((unsigned int)0x80000000)
#define BlockRange_RESERVED   ((unsigned int)0x40000000)
#define BlockRange_READONLY   ((unsigned int)0x20000000)

// Values for the Usage information (This helps map the new storage APIs to the needs of existing code)
#define BlockRange_ALL_MASK       ((unsigned int)0xFFFFFFFF)
#define BlockRange_USAGE_MASK     ((unsigned int)0x000000FF)
#define BlockRange_NON_USAGE_MASK ((unsigned int)0xFFFFFF00)

// for secondary devices to set dirtybits
#define BlockRange_BLOCKTYPE_RESERVED (BlockRange_RESERVED)
#define BlockRange_BLOCKTYPE_DIRTYBIT (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_CONFIG)
// Configuration data that contains all the unique data
#define BlockRange_BLOCKTYPE_CONFIG                                                                                    \
    (BlockRange_ATTRIB_PRIMARY | BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_CONFIG)

// Boot loader and boot strap code
#define BlockRange_BLOCKTYPE_BOOTSTRAP                                                                                 \
    (BlockRange_EXECUTABLE | BlockRange_RESERVED | BlockRange_DATATYPE_NATIVECODE | BlockUsage_BOOTSTRAP)
// CLR or other native code "application"
#define BlockRange_BLOCKTYPE_CODE                                                                                      \
    (BlockRange_EXECUTABLE | BlockRange_RESERVED | BlockRange_DATATYPE_NATIVECODE | BlockUsage_CODE)
// Deployment area for MFdeploy & Visual Studio
#define BlockRange_BLOCKTYPE_DEPLOYMENT (BlockRange_RESERVED | BlockRange_DATATYPE_MANAGEDCODE | BlockUsage_DEPLOYMENT)
// Part A of Simple Storage
#define BlockRange_BLOCKTYPE_SIMPLE_A (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_SIMPLE_A)
// Part B of Simple Storage
#define BlockRange_BLOCKTYPE_SIMPLE_B (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_SIMPLE_B)
// Part A of EWR Storage
#define BlockRange_BLOCKTYPE_STORAGE_A (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_STORAGE_A)
// Part B of EWR Storage
#define BlockRange_BLOCKTYPE_STORAGE_B (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_STORAGE_B)
// File System
#define BlockRange_BLOCKTYPE_FILESYSTEM (BlockRange_DATATYPE_RAW | BlockUsage_FILESYSTEM)
// Used for MFUpdate for firmware/assembly/etc updates
#define BlockRange_BLOCKTYPE_UPDATE (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_UPDATE)

////////////////////////////////////////////////////////
//

// typedef struct BLOCKRANGE BlockRange;

typedef struct BlockRange
{
    unsigned int RangeType;
    unsigned int StartBlock;
    unsigned int EndBlock;
} BlockRange;

#define BlockRange_GetBlockCount(block) (block.EndBlock - block.StartBlock + 1)
#define BlockRange_GetBlockUsage(block) (block.RangeType & BlockRange_USAGE_MASK)
#define BlockRange_IsDeployment(block)  ((block.RangeType & BlockRange_USAGE_MASK) == BlockUsage_DEPLOYMENT)
#define BlockRange_IsConfig(block)      ((block.RangeType & BlockRange_BLOCKTYPE_CONFIG) == BlockRange_BLOCKTYPE_CONFIG)

/////////////////////////////////////////////////////////
// Description:
//    This structure defines characteristics of a particular
//    region of a block device.
//
// Remarks:
//    There is often more than one instance of this structure for each
//    block device.
//
//    The BytesPerBlock value is an optimization to prevent the need
//    to routinely calculate it from SectorsPerBlock * DataBytesPerSector
//

// these attributes are placed at 2nd LSB
// this is to ease usage on Flash_BlockRegionInfo.Flags struct
typedef enum BlockRegionAttribute
{
    // block region is memory mapped
    BlockRegionAttribute_MemoryMapped = 0x0100,
    // programming width is 64bits
    BlockRegionAttribute_ProgramWidthIs64bits = 0x0200,

} BlockRegionAttribute;

typedef struct BLOCKREGIONINFO BlockRegionInfo;

#define BlockRegionInfo_Size(region)                           (region->NumBlocks * region->BytesPerBlock)
#define BlockRegionInfo_BlockAddress(region, blockIndex)       (region->Start + (blockIndex * region->BytesPerBlock))
#define BlockRegionInfo_OffsetFromBlock(region, address)       ((address - region->Start) % region->BytesPerBlock)
#define BlockRegionInfo_BlockIndexFromAddress(region, address) ((address - region->Start) / region->BytesPerBlock)

struct BLOCKREGIONINFO
{
    // attributes for the block region
    BlockRegionAttribute Attributes;

    // Starting Sector address
    ByteAddress Start;
<commit_msg>Add flags to support 128 and 256 bit word flash architectures (#2405)<commit_after>//
// Copyright (c) .NET Foundation and Contributors
// Portions Copyright (c) Microsoft Corporation.  All rights reserved.
// See LICENSE file in the project root for full license information.
//

#ifndef NANOPAL_BLOCKSTORAGE_H
#define NANOPAL_BLOCKSTORAGE_H

#include <nanoHAL_v2.h>
#include <target_BlockStorage.h>

/////////////////////////////////////////////////////////
// Description:
//   Definitions for the Block Storage device interface
//   for the nanoFramework
//
// Terminology:
//  Block Storage Device - device that stores data addressable
//                         as a chunk as opposed to byte or unsigned short level
//
//  Sector - smallest unit of storage for a Block device. Data is
//           read or written as a complete sector(unless the device
//           supports XIP which allows byte addresssing and reading
//           directly from the processor memory bus)
//
//  Block  - smallest eraseable unit of the storage device. A block
//           contains one or more sectors that are erased as a whole.
//           All sectors within a block are always the same size.
//
//  Region - Group of adjacent blocks that all contain sectors of the
//           same size.
//
//  Execute-In-Place (XIP) - Attribute of some storage types, NOR, ROM,
//          RAM, that allows direct execution of code from the device.
//          XIP capable devices are at least read-only and byte addresable
//          on the CPU memory bus.
//

// In flash media the distinction between a block and a sector is important
// so we define the sector address to make it clear.
typedef unsigned int ByteAddress;
typedef unsigned int SectorAddress;

//////////////////////////////////////////////////////////
// Description:
//   Flags to Indicate the status of a particular block in
//   flash. ALL sectors for a block *MUST* share the same
//   status.
//
// Remarks:
//   When the block is reserved the lower 16 bits specifies a
//   USAGE_XXXX value to indicate the purpose of the block.
//
//   The BlockRange information is technically dynamic in the
//   sense that it is not fixed or defined in hardware. Rather,
//   it is defined by the system designer. However, the BlockRange
//   info does not and *MUST* not change at run-time.  The only
//   exceptions to this rule is in the boot loader where the
//   storage device is being formated or re-laid out as part
//   of an update etc... and when an FS discovers a bad block
//   it should mark it as bad. WIthout this restriction
//   implementing an FS is virtually impossible since the FS
//   would have to deal with the possibility that the usage for
//   a Block could change at any point in time.
//
typedef enum BlockUsage
{
    BlockUsage_BOOTSTRAP = 0x0010,
    BlockUsage_CODE = 0x0020,
    BlockUsage_CONFIG = 0x0030,
    BlockUsage_FILESYSTEM = 0x0040,

    BlockUsage_DEPLOYMENT = 0x0050,

    BlockUsage_UPDATE = 0x0060,

    BlockUsage_SIMPLE_A = 0x0090,
    BlockUsage_SIMPLE_B = 0x00A0,

    BlockUsage_STORAGE_A = 0x00E0,
    BlockUsage_STORAGE_B = 0x00F0,

    BlockUsage_ANY = 0x0000,

} BlockUsage;

// upper 4 bits of USAGE_XXXX identifies the base type of info stored in the block
// using these values it is possible to scan a device for all managed code or all
// native code without worrying about the finer details of what it's for.

// Block contains XIP system native code
#define BlockRange_DATATYPE_NATIVECODE ((unsigned int)0x1000)
// Block contains managed code assemblies
#define BlockRange_DATATYPE_MANAGEDCODE ((unsigned int)0x2000)
// Block contains raw data
#define BlockRange_DATATYPE_RAW ((unsigned int)0x4000)

// use to mark the block is used for special purpose
#define BlockRange_ATTRIB_PRIMARY ((unsigned int)0x10000)

#define BlockRange_EXECUTABLE ((unsigned int)0x80000000)
#define BlockRange_RESERVED   ((unsigned int)0x40000000)
#define BlockRange_READONLY   ((unsigned int)0x20000000)

// Values for the Usage information (This helps map the new storage APIs to the needs of existing code)
#define BlockRange_ALL_MASK       ((unsigned int)0xFFFFFFFF)
#define BlockRange_USAGE_MASK     ((unsigned int)0x000000FF)
#define BlockRange_NON_USAGE_MASK ((unsigned int)0xFFFFFF00)

// for secondary devices to set dirtybits
#define BlockRange_BLOCKTYPE_RESERVED (BlockRange_RESERVED)
#define BlockRange_BLOCKTYPE_DIRTYBIT (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_CONFIG)
// Configuration data that contains all the unique data
#define BlockRange_BLOCKTYPE_CONFIG                                                                                    \
    (BlockRange_ATTRIB_PRIMARY | BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_CONFIG)

// Boot loader and boot strap code
#define BlockRange_BLOCKTYPE_BOOTSTRAP                                                                                 \
    (BlockRange_EXECUTABLE | BlockRange_RESERVED | BlockRange_DATATYPE_NATIVECODE | BlockUsage_BOOTSTRAP)
// CLR or other native code "application"
#define BlockRange_BLOCKTYPE_CODE                                                                                      \
    (BlockRange_EXECUTABLE | BlockRange_RESERVED | BlockRange_DATATYPE_NATIVECODE | BlockUsage_CODE)
// Deployment area for MFdeploy & Visual Studio
#define BlockRange_BLOCKTYPE_DEPLOYMENT (BlockRange_RESERVED | BlockRange_DATATYPE_MANAGEDCODE | BlockUsage_DEPLOYMENT)
// Part A of Simple Storage
#define BlockRange_BLOCKTYPE_SIMPLE_A (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_SIMPLE_A)
// Part B of Simple Storage
#define BlockRange_BLOCKTYPE_SIMPLE_B (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_SIMPLE_B)
// Part A of EWR Storage
#define BlockRange_BLOCKTYPE_STORAGE_A (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_STORAGE_A)
// Part B of EWR Storage
#define BlockRange_BLOCKTYPE_STORAGE_B (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_STORAGE_B)
// File System
#define BlockRange_BLOCKTYPE_FILESYSTEM (BlockRange_DATATYPE_RAW | BlockUsage_FILESYSTEM)
// Used for MFUpdate for firmware/assembly/etc updates
#define BlockRange_BLOCKTYPE_UPDATE (BlockRange_RESERVED | BlockRange_DATATYPE_RAW | BlockUsage_UPDATE)

////////////////////////////////////////////////////////
//

// typedef struct BLOCKRANGE BlockRange;

typedef struct BlockRange
{
    unsigned int RangeType;
    unsigned int StartBlock;
    unsigned int EndBlock;
} BlockRange;

#define BlockRange_GetBlockCount(block) (block.EndBlock - block.StartBlock + 1)
#define BlockRange_GetBlockUsage(block) (block.RangeType & BlockRange_USAGE_MASK)
#define BlockRange_IsDeployment(block)  ((block.RangeType & BlockRange_USAGE_MASK) == BlockUsage_DEPLOYMENT)
#define BlockRange_IsConfig(block)      ((block.RangeType & BlockRange_BLOCKTYPE_CONFIG) == BlockRange_BLOCKTYPE_CONFIG)

/////////////////////////////////////////////////////////
// Description:
//    This structure defines characteristics of a particular
//    region of a block device.
//
// Remarks:
//    There is often more than one instance of this structure for each
//    block device.
//
//    The BytesPerBlock value is an optimization to prevent the need
//    to routinely calculate it from SectorsPerBlock * DataBytesPerSector
//

// these attributes are placed at 2nd LSB
// this is to ease usage on Flash_BlockRegionInfo.Flags struct
typedef enum BlockRegionAttribute
{
    // block region is memory mapped
    BlockRegionAttribute_MemoryMapped = 0x0100,

    // Flash word size 64 bits
    BlockRegionAttribute_ProgramWidthIs64bits = 0x0200,
    // Flash word size 128 bits
    BlockRegionAttribute_ProgramWidthIs128bits = 0x0400,
    // Flash word size 256 bits
    BlockRegionAttribute_ProgramWidthIs256bits = 0x0800,

} BlockRegionAttribute;

typedef struct BLOCKREGIONINFO BlockRegionInfo;

#define BlockRegionInfo_Size(region)                           (region->NumBlocks * region->BytesPerBlock)
#define BlockRegionInfo_BlockAddress(region, blockIndex)       (region->Start + (blockIndex * region->BytesPerBlock))
#define BlockRegionInfo_OffsetFromBlock(region, address)       ((address - region->Start) % region->BytesPerBlock)
#define BlockRegionInfo_BlockIndexFromAddress(region, address) ((address - region->Start) / region->BytesPerBlock)

struct BLOCKREGIONINFO
{
    // attributes for the block region
    BlockRegionAttribute Attributes;

    // Starting Sector address
    ByteAddress Start;

{'fraction_non_alphanumeric': 0.08911836685966693, 'fraction_numerical': 0.017549095684355042, 'mean_word_length': 3.078383641674781, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 8, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7574393', 'n_tokens_mistral': 4808, 'n_tokens_neox': 4481, 'n_words': 1600}