<commit_before>/* CMSIS-DAP Interface Firmware
 * Copyright (c) 2009-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <RTL.h>
#include <rl_usb.h>
#include <string.h>

#include "target_flash.h"
#include "target_reset.h"
#include "DAP_config.h"
#include "dap.h"
#include "main.h"
#include "tasks.h"
#include "semihost.h"
#include "version.h"
#include "swd_host.h"
#include "usb_buf.h"
#include "virtual_fs.h"

extern uint32_t usb_buffer[];

void usbd_msc_init ()
{    
    // config the mbr and FAT - FAT may be const later
    virtual_fs_init();
    
    USBD_MSC_MemorySize = mbr.bytes_per_sector * mbr.total_logical_sectors;
    USBD_MSC_BlockSize  = mbr.bytes_per_sector;
    USBD_MSC_BlockGroup = 1;
    USBD_MSC_BlockCount = USBD_MSC_MemorySize / USBD_MSC_BlockSize;
    USBD_MSC_BlockBuf   = (uint8_t *)usb_buffer;

    USBD_MSC_MediaReady = __TRUE;
}

void usbd_msc_read_sect (U32 block, U8 *buf, U32 num_of_blocks)
{
    fs_items_t fs_read_info = {0,0};
    uint32_t req_block_offset = block * USBD_MSC_BlockSize;
    uint32_t max_size_current_fs_entry = 0;
    uint32_t sector_offset = 0;
    uint8_t i = 0, real_data_present = 1;
    
    // dont proceed if we're not ready
    if (!USBD_MSC_MediaReady) {
        return;
    }
    
    // find the location of the data that is being requested by the host
    //  convert block * block size into an index of the flat file system
    // fs[i].length 0 is a dummy end sector (break below loop)
    // fs_read_info.sect is a pointer to the sector we need data from (break below loop)
    while((fs[i].length != 0) && (fs_read_info.sect == 0)) {
        // accumulate the length of the sectors
        max_size_current_fs_entry += fs[i].length;
        // the data is in this entry. See if we know it or need to send 0's
        if (req_block_offset < max_size_current_fs_entry) {
            fs_read_info.sect = fs[i].sect;
            // can take more than one block for a sector entry - normalize the block number for a given entry
            sector_offset = fs[i].length - (max_size_current_fs_entry - (block * USBD_MSC_BlockSize));
            // determine if the inflated size is greater than the real size. If so pad with 0
            if(sector_offset >= sizeof(fs[i].sect)) {
                real_data_present = 0;
            }
        }
        i++;
    }
    // now send the data if a known sector and valid data in memory - otherwise send 0's
    if (fs_read_info.sect != 0 && real_data_present == 1) {
        memcpy(buf, &fs_read_info.sect[sector_offset], num_of_blocks * USBD_MSC_BlockSize);
    }
    else {
        memset(buf, 0, num_of_blocks * USBD_MSC_BlockSize);
    }
}

#define DEBUG_MSC_FILE_TRANSFER
#include "stdio.h"

// known extension types
// CRD - chrome
// PAR - IE
static const char *known_extensions[] = {
    "BIN",
    "bin",
    0,
};

typedef enum extension {
    UNKNOWN = -1,
    BIN,
} extension_t;

static uint32_t extension_is_known(const FatDirectoryEntry_t dir_entry)
{
    uint32_t i = 0;
    while (known_extensions[i] != 0) {
        if (0 == strncmp(known_extensions[i], (const char *)&dir_entry.filename[8], 3)) {
            // we may see the entry with a false filesize. Validate both or keep looking
            return (dir_entry.filesize) ? dir_entry.filesize : 0;
        }
        i++;
    }
    return 0;
}

#define DBG_PRINT_BLOCK
static inline void print_block(uint32_t block)
{
    char block_msg[32] = {0};
    sprintf(block_msg, "block: %d\r\n", block);
    USBD_CDC_ACM_DataSend((uint8_t *)&block_msg, strlen(block_msg));
    os_dly_wait(1);
}

//#define DBG_COMPARE_BLOCK
static inline void compare_block(uint32_t block, uint8_t *buf)
{
    int32_t result = 0;
    char msg[32] = {0};
    // only RAM elements are mbr, fat1 and fat2 which is a copy of fat1
    if ((block == (mbr.logical_sectors_per_fat+1)) ||
        (block == 1)  ||
        (block == 0)) {
        result = memcmp(fs[block].sect, buf, USBD_MSC_BlockSize);
        if (0 != result) {
            sprintf(msg, "Block compare failed: %d %d\r\n", block, result);
            USBD_CDC_ACM_DataSend((uint8_t *)msg, strlen(msg));
        }
        else {
            sprintf(msg, "Block compare passed: %d\r\n", block);
            USBD_CDC_ACM_DataSend((uint8_t *)msg, strlen(msg));
        }
    }
}

#define DBG_ROOT_DIR
static inline void log_root_dir(FatDirectoryEntry_t dir)
{
    // should be the root dir - testing linux write data file before root dir
    char msg[64] = {0};
    sprintf(msg, "name:%s\t - size:%d\t - start:%d\r\n", dir.filename, dir.filesize, dir.first_cluster_low_16);
    USBD_CDC_ACM_DataSend((uint8_t *)&msg, strlen(msg));
    os_dly_wait(1);
}

static inline void print(char *log)
{
    // should be the root dir - testing linux write data file before root dir
    char msg[64] = {0};
    sprintf(msg, "%s\r\n", log);
    USBD_CDC_ACM_DataSend((uint8_t *)&msg, strlen(msg));
    os_dly_wait(1);
}

//#define DBG_FILE_DATA
static inline void cdc_write_file_data(uint8_t *buf)
{
    USBD_CDC_ACM_DataSend(buf, USBD_MSC_BlockSize);
    os_dly_wait(10);
}

static struct {
    uint32_t  start_block;
    uint32_t amt_to_write;
    uint32_t amt_written;<commit_msg>validate first character as this has meaning. Add more dir entry data to the logs<commit_after>/* CMSIS-DAP Interface Firmware
 * Copyright (c) 2009-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <RTL.h>
#include <rl_usb.h>
#include <string.h>

#include "target_flash.h"
#include "target_reset.h"
#include "DAP_config.h"
#include "dap.h"
#include "main.h"
#include "tasks.h"
#include "semihost.h"
#include "version.h"
#include "swd_host.h"
#include "usb_buf.h"
#include "virtual_fs.h"

extern uint32_t usb_buffer[];

void usbd_msc_init ()
{    
    // config the mbr and FAT - FAT may be const later
    virtual_fs_init();
    
    USBD_MSC_MemorySize = mbr.bytes_per_sector * mbr.total_logical_sectors;
    USBD_MSC_BlockSize  = mbr.bytes_per_sector;
    USBD_MSC_BlockGroup = 1;
    USBD_MSC_BlockCount = USBD_MSC_MemorySize / USBD_MSC_BlockSize;
    USBD_MSC_BlockBuf   = (uint8_t *)usb_buffer;

    USBD_MSC_MediaReady = __TRUE;
}

void usbd_msc_read_sect (U32 block, U8 *buf, U32 num_of_blocks)
{
    fs_items_t fs_read_info = {0,0};
    uint32_t req_block_offset = block * USBD_MSC_BlockSize;
    uint32_t max_size_current_fs_entry = 0;
    uint32_t sector_offset = 0;
    uint8_t i = 0, real_data_present = 1;
    
    // dont proceed if we're not ready
    if (!USBD_MSC_MediaReady) {
        return;
    }
    
    // find the location of the data that is being requested by the host
    //  convert block * block size into an index of the flat file system
    // fs[i].length 0 is a dummy end sector (break below loop)
    // fs_read_info.sect is a pointer to the sector we need data from (break below loop)
    while((fs[i].length != 0) && (fs_read_info.sect == 0)) {
        // accumulate the length of the sectors
        max_size_current_fs_entry += fs[i].length;
        // the data is in this entry. See if we know it or need to send 0's
        if (req_block_offset < max_size_current_fs_entry) {
            fs_read_info.sect = fs[i].sect;
            // can take more than one block for a sector entry - normalize the block number for a given entry
            sector_offset = fs[i].length - (max_size_current_fs_entry - (block * USBD_MSC_BlockSize));
            // determine if the inflated size is greater than the real size. If so pad with 0
            if(sector_offset >= sizeof(fs[i].sect)) {
                real_data_present = 0;
            }
        }
        i++;
    }
    // now send the data if a known sector and valid data in memory - otherwise send 0's
    if (fs_read_info.sect != 0 && real_data_present == 1) {
        memcpy(buf, &fs_read_info.sect[sector_offset], num_of_blocks * USBD_MSC_BlockSize);
    }
    else {
        memset(buf, 0, num_of_blocks * USBD_MSC_BlockSize);
    }
}

#define DEBUG_MSC_FILE_TRANSFER
#include "stdio.h"

// known extension types
// CRD - chrome
// PAR - IE
static const char *known_extensions[] = {
    "BIN",
    "bin",
    0,
};

typedef enum extension {
    UNKNOWN = -1,
    BIN,
} extension_t;

static uint32_t first_byte_valid(uint8_t c)
{
    const char *valid_char = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    do {
        if(c == *valid_char) {
            return 1;
        }
    } while (*(valid_char++) != '\0');
    return 0;
}        

static uint32_t extension_is_known(const FatDirectoryEntry_t dir_entry)
{
    uint32_t i = 0;
    while (known_extensions[i] != 0) {
        if(1 == first_byte_valid(dir_entry.filename[0])) {
            if (0 == strncmp(known_extensions[i], (const char *)&dir_entry.filename[8], 3)) {
                // we may see the entry with a false filesize. Validate both or keep looking
                return (dir_entry.filesize) ? dir_entry.filesize : 0;
            }
        }
        i++;
    }
    return 0;
}

#define DBG_PRINT_BLOCK
static inline void print_block(uint32_t block)
{
    char block_msg[32] = {0};
    sprintf(block_msg, "block: %d\r\n", block);
    USBD_CDC_ACM_DataSend((uint8_t *)&block_msg, strlen(block_msg));
    os_dly_wait(1);
}

//#define DBG_COMPARE_BLOCK
static inline void compare_block(uint32_t block, uint8_t *buf)
{
    int32_t result = 0;
    char msg[32] = {0};
    // only RAM elements are mbr, fat1 and fat2 which is a copy of fat1
    if ((block == (mbr.logical_sectors_per_fat+1)) ||
        (block == 1)  ||
        (block == 0)) {
        result = memcmp(fs[block].sect, buf, USBD_MSC_BlockSize);
        if (0 != result) {
            sprintf(msg, "Block compare failed: %d %d\r\n", block, result);
            USBD_CDC_ACM_DataSend((uint8_t *)msg, strlen(msg));
        }
        else {
            sprintf(msg, "Block compare passed: %d\r\n", block);
            USBD_CDC_ACM_DataSend((uint8_t *)msg, strlen(msg));
        }
    }
}

#define DBG_ROOT_DIR
static inline void log_root_dir(FatDirectoryEntry_t dir)
{
    // should be the root dir - testing linux write data file before root dir
    char msg[128] = {0};
    sprintf(msg, "name:%.11s\tattributes:%8d\tsize:%8d\tstart:%8d\tcreated:%8d\tmodified:%8d\taccessed:%8d\r\n"
        , dir.filename, dir.attributes, dir.filesize, dir.first_cluster_low_16, dir.creation_time_ms, dir.modification_time, dir.accessed_date);
    USBD_CDC_ACM_DataSend((uint8_t *)&msg, strlen(msg));
    os_dly_wait(1);
}

static inline void print(char *log)
{
    // should be the root dir - testing linux write data file before root dir
    char msg[64] = {0};
    sprintf(msg, "%s\r\n", log);
    USBD_CDC_ACM_DataSend((uint8_t *)&msg, strlen(msg));
    os_dly_wait(1);
}

//#define DBG_FILE_DATA
static inline void cdc_write_file_data(uint8_t *buf)
{
    USBD_CDC_ACM_DataSend(buf, USBD_MSC_BlockSize);
    os_dly_wait(10);
}

static struct {
    uint32_t  start_block;
    uint32_t amt_to_write;
    uint32_t amt_written;
{'fraction_non_alphanumeric': 0.10884808013355593, 'fraction_numerical': 0.01944908180300501, 'mean_word_length': 2.979076718698107, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3381678', 'n_tokens_mistral': 4323, 'n_tokens_neox': 4135, 'n_words': 1161}