⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 5 页
字号:

		charcpy((unsigned char *)&temp, (unsigned char *)img, sizeof(temp));

        if (temp.name[0] != (unsigned char)0xFF) {
            printf("%-16s  0x%08lX  0x%08lX  0x%08lX  0x%08lX\n", temp.name, 
                   temp.flash_base, 
#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
                   show_cksums ? temp.file_cksum : temp.mem_base, 
                   show_datalen ? temp.data_length : temp.size, 
#else
                   temp.mem_base, 
                   temp.size, 
#endif
                   temp.entry_point);
        }
    }
}

static void
fis_free(int argc, char *argv[])
{
    unsigned long *fis_ptr, *fis_end;
    unsigned long *area_start;

    // Do not search the area reserved for pre-RedBoot systems:
    fis_ptr = (unsigned long *)((unsigned long)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
    fis_end = (unsigned long *)(unsigned long)flash_end;
    area_start = fis_ptr;
    while (fis_ptr < fis_end) {
        if (*fis_ptr != (unsigned long)0xFFFFFFFF) {
            if (area_start != fis_ptr) {
                // Assume that this is something
                printf("  0x%08lX .. 0x%08lX\n",
                       (unsigned long)area_start, (unsigned long)fis_ptr);
            }
            // Find next blank block
            area_start = fis_ptr;
            while (area_start < fis_end) {
                if (*area_start == (unsigned long)0xFFFFFFFF) {
                    break;
                }
                area_start += block_size / sizeof(unsigned long);
            }
            fis_ptr = area_start;
        } else {
            fis_ptr += block_size / sizeof(unsigned long);
        }
    }
    if (area_start != fis_ptr) {
        printf("  0x%08lX .. 0x%08lX\n", 
               (unsigned long)area_start, (unsigned long)fis_ptr);
    }
}

// Find the first unused area of flash which is long enough
static bool
fis_find_free(unsigned long *addr, unsigned long length)
{
    unsigned long *fis_ptr, *fis_end;
    unsigned long *area_start;

    // Do not search the area reserved for pre-RedBoot systems:
    fis_ptr = (unsigned long *)((unsigned long)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
    fis_end = (unsigned long *)(unsigned long)flash_end;
    area_start = fis_ptr;
    while (fis_ptr < fis_end) {
        if (*fis_ptr != (unsigned long)0xFFFFFFFF) {
            if (area_start != fis_ptr) {
                // Assume that this is something
                if ((fis_ptr-area_start) >= (length/sizeof(unsigned long))) {
                    *addr = (unsigned long)area_start;
                    return true;
                }
            }
            // Find next blank block
            area_start = fis_ptr;
            while (area_start < fis_end) {
                if (*area_start == (unsigned long)0xFFFFFFFF) {
                    break;
                }
                area_start += block_size / sizeof(unsigned long);
            }
            fis_ptr = area_start;
        } else {
            fis_ptr += block_size / sizeof(unsigned long);
        }
    }
    if (area_start != fis_ptr) {
        if ((fis_ptr-area_start) >= (length/sizeof(unsigned long))) {
            *addr = (unsigned long)area_start;
            return true;
        }
    }
    return false;
}

static void
fis_create(int argc, char *argv[])
{
    int i, stat;
    unsigned long mem_addr, exec_addr, flash_addr, entry_addr, length, img_size;
    char *name;
    bool mem_addr_set = false;
    bool exec_addr_set = false;
    bool entry_addr_set = false;
    bool flash_addr_set = false;
    bool length_set = false;
    bool img_size_set = false;
    bool no_copy = false;
    void *fis_addr, *err_addr;
    struct fis_image_desc *img;
    bool slot_found, defaults_assumed;
    struct option_info opts[7];
    bool prog_ok = false;
	bool overlap = false;

    init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
              (void **)&mem_addr, (bool *)&mem_addr_set, "memory base address");
    init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM, 
              (void **)&exec_addr, (bool *)&exec_addr_set, "ram base address");
    init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM, 
              (void **)&entry_addr, (bool *)&entry_addr_set, "entry point address");
    init_opts(&opts[3], 'f', true, OPTION_ARG_TYPE_NUM, 
              (void **)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
    init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM, 
              (void **)&length, (bool *)&length_set, "image length [in FLASH]");
    init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM, 
              (void **)&img_size, (bool *)&img_size_set, "image size [actual data]");
    init_opts(&opts[6], 'n', false, OPTION_ARG_TYPE_FLG, 
              (void **)&no_copy, (bool *)0, "don't copy from RAM to FLASH, just update directory");
    if (!scan_opts(argc, argv, 2, opts, 7, (void *)&name, OPTION_ARG_TYPE_STR, "file name"))
    {
        fis_usage("invalid arguments");
        return;
    }

    defaults_assumed = false;
    if (name) {
        // Search existing files to acquire defaults for params not specified:
        fis_addr = (void *)((unsigned long)flash_end - block_size);
        charcpy(fis_work_block, fis_addr, block_size);
        img = (struct fis_image_desc *)fis_work_block;
        for (i = 0;  i < block_size/sizeof(*img);  i++, img++) {
            if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) {
                // Found it, so get any unset but necessary params from there:
                if (!length_set) {
                    length_set = true;
                    length = img->size;
                    defaults_assumed = true;
                }
                if (!exec_addr_set) {
                    // Preserve "normal" behaviour
                    exec_addr_set = true;
                    exec_addr = flash_addr_set ? flash_addr : mem_addr;
                }           
                if (!flash_addr_set) {
                    flash_addr_set = true;
                    flash_addr = img->flash_base;
                    defaults_assumed = true;
                }           
                break;
            }
        }
    }

    if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) ||
        !length_set || !name) {
        fis_usage("required parameter missing");
        return;
    }
    if (!img_size_set) {
        img_size = length;
    }
    // 'length' is size of FLASH image, 'img_size' is actual data size
    // Round up length to FLASH block size
#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
    length = ((length + block_size - 1) / block_size) * block_size;
    if (length < img_size) {
        printf("Invalid FLASH image size/length combination\n");
        return;
    }
#endif
    if (flash_addr_set &&
        ((stat = flash_verify_addr((void *)flash_addr)) ||
         (stat = flash_verify_addr((void *)(flash_addr+img_size-1))))) {
        printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
        printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
        return;
    }
    if (flash_addr_set && flash_addr & (block_size-1)) {
        printf("Invalid FLASH address: %p\n", (void *)flash_addr);
        printf("   must be 0x%x aligned\n", block_size);
        return;
    }
    if (strlen(name) >= sizeof(img->name)) {
        printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name));
        return;
    }
    if (!no_copy) {
        if ((mem_addr < (unsigned long)ram_start) ||
            ((mem_addr+img_size) >= (unsigned long)ram_end)) {
            printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
            printf("   valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
        }
        if (!flash_addr_set && !fis_find_free(&flash_addr, length)) {
            printf("Can't locate %ld bytes free in FLASH\n", length);
            return;
        }
    }
    // Find a slot in the directory for this entry
    // First, see if an image by this name is already present
    slot_found = false;
    fis_addr = (void *)((unsigned long)flash_end - block_size);
    charcpy(fis_work_block, fis_addr, block_size);
    img = (struct fis_image_desc *)fis_work_block;
    for (i = 0;  i < block_size/sizeof(*img);  i++, img++) {
        if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) {
            if (flash_addr_set && (img->flash_base != flash_addr)) {
                printf("Image found, but FLASH address incorrect\n");
                return;
            }
            if (img->size != length) {
                printf("Image found, but LENGTH is incorrect (0x%lx != 0x%lx)\n", img->size, length);
                return;
            }
            if (!verify_action("An image named '%s' exists", name)) {
                return;
            } else {                
                slot_found = true;
                if (defaults_assumed) {
                    if (!verify_action("* CAUTION * about to program '%s'\n            at %p..%p from %p", 
                                       name, (void *)flash_addr, (void *)(flash_addr+img_size-1),
                                       (void *)mem_addr)) {
                        return;  // The guy gave up
                    }
                }
                break;
            }
        }
    }
    // If not found, try and find an empty slot
    if (!slot_found) {
        img = (struct fis_image_desc *)fis_work_block;
        for (i = 0;  i < block_size/sizeof(*img);  i++, img++) {
            if (img->name[0] == (unsigned char)0xFF) {
                slot_found = true;
                break;
            }
        }
    }
    if (!no_copy) {
        // Safety check - make sure the address range is not within the code we're running
        if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+img_size-1), &overlap)) {
            return;
        }
		if(overlap)
		{
			flash_unlock((void *)flash_addr, length, (void **)&err_addr);
		}
        prog_ok = true;
        if (prog_ok) {
            // Erase area to be programmed
            if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
                printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
                prog_ok = false;
            }
        }
        if (prog_ok) {
            // Now program it
            if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) {
                printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
                prog_ok = false;
            }
        }
		if(overlap)
		{
			flash_lock((void *)flash_addr, length, (void **)&err_addr);
		}
    }
    if (prog_ok) {
        // Update directory
        memset(img, 0, sizeof(*img));
        strcpy(img->name, name);
        img->flash_base = flash_addr;
        img->mem_base = exec_addr_set ? exec_addr : (flash_addr_set ? flash_addr : mem_addr);
        img->entry_point = entry_addr_set ? entry_addr : (unsigned long)entry_address;  // Hope it's been set
        img->size = length;
        img->data_length = img_size;
#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
        img->file_cksum = crc32((unsigned char *)flash_addr, img_size);
#endif
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
        // Insure [quietly] that the directory is unlocked before trying to update
        flash_unlock((void *)fis_addr, block_size, (void **)&err_addr);
#endif
        if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) {
            printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
            // Don't try to program if the erase failed
        } else {
            // Now program it
            if ((stat = flash_program((void *)fis_addr, (void *)fis_work_block, block_size, (void **)&err_addr)) != 0) {
                printf("Error programming at %p: %s\n", err_addr, flash_errmsg(stat));
            }
        }
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
        // Insure [quietly] that the directory is locked after the update
        flash_lock((void *)fis_addr, block_size, (void **)&err_addr);
#endif
    }
}

static void
fis_delete(int argc, char *argv[])
{
    char *name;
    int i, stat;
    void *fis_addr, *err_addr;
    struct fis_image_desc *img;
    bool slot_found;

    if (!scan_opts(argc, argv, 2, 0, 0, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
    {
        fis_usage("invalid arguments");
        return;
    }

    slot_found = false;
    fis_addr = (void *)((unsigned long)flash_end - block_size);
    charcpy(fis_work_block, fis_addr, block_size);
    img = (struct fis_image_desc *)fis_work_block;
    i = 0;
#ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
    i++;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT
    i++;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
    i++;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
    i++;
#endif
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
    i++;
#endif
#if 1 // And the descriptor for the descriptor table itself
    i++;
#endif
    img += i;  // Skip reserved files

    for ( /* i, img */;  i < block_size/sizeof(*img);  i++, img++) {
        if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) {
            if (!verify_action("Delete image '%s'", name)) {
                return;
            } else {
                slot_found = true;
                break;
            }
        }
    }
    if (!slot_found) {
        printf("No image '%s' found\n", name);
        return;
    }
    // Erase Data blocks (free space)
    if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
        printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
    }
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
    // Insure [quietly] that the directory is unlocked before trying to update
    flash_unlock((void *)fis_addr, block_size, (void **)&err_addr);
#endif
    // Update directory
    memset(img, 0xFF, sizeof(*img));
    if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) {
        printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
        // Don't try to program if the erase failed

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -