flashdir.c
来自「采用ST20 CPU的机顶盒的烧写程序」· C语言 代码 · 共 890 行 · 第 1/2 页
C
890 行
/*
* File : flashdir.c
* Synopsys : Target-side utility to display the contents of FLASH
*
* Copyright (c) 2003-2007 STMicroelectronics Limited. All right reserved.
*/
#ifdef FLASHERPLATFORM
#define _stringify(s) #s
#define STRINGIFY(s) _stringify(s)
#define DEFAULTPLATFORM STRINGIFY(FLASHERPLATFORM)
#else
#error FLASHERPLATFORM undefined
#endif
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#undef __STRICT_ANSI__
#include <string.h>
#include "flash.h"
/*
* getopt () prototypes & globals
*/
extern int getopt(int argc, char* const* argv, const char* optstring);
extern char* optarg;
extern int optind;
static char* blockMapFile = NULL;
static char* romImage = NULL;
static int fullOption = 0;
static flashTarget_t* target = NULL;
/*
* Structure to record attributes of a region
* of FLASH.
*/
typedef struct region_s region_t;
struct region_s
{
region_t* next;
region_t* prev;
unsigned int address;
unsigned int length;
const char* use;
};
static region_t regions = { ®ions, ®ions, 0, 0, NULL };
/*
* Routine to report command usage, and abort
*/
static void usage(const char* msg)
{
fprintf(stderr, "flashdir: %s\n"
"Usage: flashdir [-f] [-r <input rom image>] [-t <target board>]\n"
" flashdir [-m <block map output file>] [-t <target board>]\n\n"
"-f : dump full details of FLASH usage\n"
"-m <block_map_file>\n"
" : dump FLASH block map to block_map_file (can then use with -flashmap\n"
" to mkbinrom.pl)\n"
"-r <rom_image_file>\n"
" : read 'directory' information from a ROM image instead of FLASH memory\n"
"-t <board> : override default target board ("DEFAULTPLATFORM")\n"
" %s\n",
msg, flashGetTargetNames());
exit(1);
}
/*
* Reads bootPages and imageDirectoryPages from a binary ROM image and returns
* the size of the image.
*/
unsigned int readFromBinROM(char* romImage, bootPages_t* bootPages, imageDirectoryPages_t* imageDirectoryPages)
{
FILE* fp;
if (!(fp = fopen(romImage, "rb")))
{
fprintf(stderr, "flashdir: Failed to open %s\n", romImage);
exit(1);
}
#if defined(__mb390__) || defined(__mb424__) || defined(__mb435__)
/* The bootPages start at offset end of file - sizeof(bootPages_t) */
if (0 != fseek(fp, -sizeof(bootPages_t), SEEK_END))
{
fprintf(stderr, "flashdir: Failed to seek to boot pages in %s\n", romImage);
exit(1);
}
#else
/* The bootPages start at offset FLASH_BASE - FLASH_START */
if (FLASH_BASE != FLASH_START)
{
if (0 != fseek(fp, FLASH_BASE - FLASH_START, SEEK_SET))
{
fprintf(stderr, "flashdir: Failed to seek to boot pages in %s\n", romImage);
exit(1);
}
}
#endif /* defined(__mb390__) || defined(__mb424__) || defined(__mb435__) */
if (1 != fread(bootPages, sizeof(bootPages_t), 1, fp))
{
fprintf(stderr, "flashdir: Failed to read boot pages from %s\n", romImage);
exit(1);
}
if (0 != fseek(fp, (unsigned int)bootPages->imageControlDirectoryPtr - FLASH_START, SEEK_SET))
{
fprintf(stderr, "flashdir: Failed to seek to image directory pages in %s\n", romImage);
exit(1);
}
if (1 != fread(imageDirectoryPages, sizeof(imageDirectoryPages_t), 1, fp))
{
fprintf(stderr, "flashdir: Failed to read image directory pages from %s\n", romImage);
exit(1);
}
fclose(fp);
/*
* Return the size of the binary file as our flash size
*/
{
struct stat s;
stat(romImage, &s);
return s.st_size;
}
}
/*
* Routine to read a line from a file (given descriptor and a destination string)
* Returns 0 on end of file
* (Grabbed from the ST20 flash example)
*/
static int Gets(long int fd, char* dest, int restart)
{
int sLength = 1;
static char bData[4096];
static long int offset;
static long int length;
static int eof;
if (restart)
{
length = 0; eof = 0;
}
while(1)
{
while(offset < length)
{
if(bData[offset] == '\n')
{
offset++;
*dest = '\0';
return sLength;
}
*dest = bData[offset];
dest++;
offset++;
sLength++;
}
if(eof)
return 0;
length = read(fd, bData, sizeof(bData));
offset = 0;
eof = length < sizeof(bData);
}
}
/*
* Routine that reads a space delimited element from a src string and copies it
* into dest.
* (Grabbed from the ST20 flash example)
*/
static char* GetElement(char* src, char* dest)
{
if(!src)
return NULL;
for(;;)
{
if(*src == ' ')
{
*dest = '\0';
return src + 1;
}
if(*src == '\0')
{
*dest = '\0';
return NULL;
}
*dest++ = *src++;
}
}
/*
* Routine that reads and parses a line from a hex file into array dest, giving
* the line address in address and number of bytes in length.
* Returns 0 on success, 1 on failure
* (Grabbed from the ST20 flash example, and modified to do allocation)
*/
static int ReadHexLine(int fd, unsigned int* address, unsigned char** dest, int* length)
{
char buffer[1024];
char element[64];
char lineBytes[4096];
char* lineBytesPtr;
char* ptr;
long slen;
unsigned int tmp;
slen = Gets(fd, buffer, (0 == lseek(fd, 0, SEEK_CUR)));
if(!slen)
return 1;
ptr = buffer;
/* Get Address */
ptr = GetElement(ptr, element);
if (sscanf( element, "%x", &tmp))
*address = tmp ;
*length = 0;
lineBytesPtr = lineBytes;
while(ptr)
{
ptr = GetElement(ptr, element);
if (sscanf( element, "%x", &tmp))
*lineBytesPtr++ = (unsigned char)tmp;
(*length)++;
}
/* allocate dest and copy lineBytes into it */
*dest = malloc(*length);
memcpy(*dest, lineBytes, *length);
return 0;
}
/*
* Fill some allocated memory from an open HEX file using the given memory range.
* Store the highest read address from the HEX file in *highestAddr.
*/
void fillFromHexFile(int fd, char* toFill, unsigned long lowAddr, unsigned long size, unsigned long* highestAddr)
{
int lineNumBytes;
long offset;
unsigned int lineAddr = 0;
unsigned char* lineBytes = NULL;
/* printf("Filling data from 0x%08x to 0x%08x\n", lowAddr, lowAddr + size);*/
lseek(fd, 0, SEEK_SET);
while(!ReadHexLine(fd, &lineAddr, &lineBytes, &lineNumBytes))
{
if (*highestAddr < lineAddr + lineNumBytes)
*highestAddr = lineAddr + lineNumBytes;
offset = lineAddr - lowAddr;
if (offset + lineNumBytes < 0 || offset >= (long)size)
{
/* No overlap */
free(lineBytes);
continue;
}
else
{
int i;
for (i = 0; i < lineNumBytes; i++)
{
if (offset + i >= 0 && offset + i < size)
{
toFill[offset + i] = lineBytes[i];
/* printf("0x%02x at 0x%08x (offset 0x%08x)\n", lineBytes[i], lineAddr + i, offset + i);*/
}
}
}
free(lineBytes);
}
}
/*
* Reads bootPages and imageDirectoryPages from a hex ROM image and returns
* the top set offset from FLASH_START in the image.
*/
unsigned int readFromHexROM(char* romImage, bootPages_t* bootPages, imageDirectoryPages_t* imageDirectoryPages)
{
/* This is implemented as a 2-pass read, reading first the bootPages and then
the imageDirectoryPages (we can't do both at the same time as we don't know
where the imageDirectoryPages are until we have the address stored in the
bootPages).
*/
int fd;
unsigned long lowAddr, size, highestAddr = 0;
if ((fd = open(romImage, O_RDONLY)) == -1)
{
fprintf(stderr, "flashdir: Failed to open %s\n", romImage);
exit(1);
}
size = sizeof(bootPages_t);
#if defined(__mb390__) || defined(__mb424__) || defined(__mb435__)
lowAddr = 0x80000000 - sizeof(bootPages_t);
#else
lowAddr = FLASH_BASE;
#endif /* defined(__mb390__) || defined(__mb424__) || defined(__mb435__) */
/* Fill bootPages with Hex from lowAddr to lowAddr + size */
fillFromHexFile(fd, (char*)bootPages, lowAddr, size, &highestAddr);
/* Now fill the imageDirectoryPages */
lowAddr = (unsigned int)bootPages->imageControlDirectoryPtr;
size = sizeof(imageDirectoryPages_t);
fillFromHexFile(fd, (char*)imageDirectoryPages, lowAddr, size, &highestAddr);
close(fd);
/* Return the highest offset from FLASH_BASE found. */
return highestAddr - FLASH_BASE;
}
/*
* Routine to insert a region behind another one in a list
*/
static void insertBehind(region_t* new, region_t* listNode)
{
new->next = listNode;
new->prev = listNode->prev;
listNode->prev->next = new;
listNode->prev = new;
}
/*
* Routine to add a newly discovered region to the
* FLASH memory map. We maintain the memory map in
* ascending address order
*/
static void recordRegion(unsigned int address, unsigned int length, char* description)
{
region_t* newRegion;
region_t* ptr;
if ((newRegion = malloc(sizeof(region_t))) == NULL)
{
fprintf(stderr, "flashdir: Out of memory\n");
exit(1);
}
newRegion->address = address;
newRegion->length = length;
newRegion->use = description;
for (ptr = regions.next; ptr != ®ions; ptr = ptr->next)
{
if (ptr->address > newRegion->address)
{
if ((newRegion->address + newRegion->length) > ptr->address)
{
fprintf(stderr, "flashdir: FLASH is corrupt - overlapping regions detected.\n");
exit(1);
}
break;
}
}
insertBehind(newRegion, ptr);
}
/*
* Routine to print info on an image
*/
static void printImageInfo(int slot, imageControl_t* element, int printBanner)
{
int j;
static const char* types[] = {
"in place", "copy", "zeroed", "run length", "deflated", "symbols", "relocations", "LX_BOOT"
};
imageSection_t* section = element->sections;
int isSigDMA = (element->CPU & FLASH_IMAGE_TYPE_MASK) == FLASH_IMAGE_TYPE_CC_SIGDMA;
if (printBanner)
{
printf("\n Slot CPU Identifier Start Stack\n");
printf(" -----------------------------------------------------------------------\n");
}
if (element->CPU & FLASH_IMAGE_TYPE_MASK)
{
/* It's an image type other than a standard application */
int isData = (element->CPU & FLASH_IMAGE_TYPE_MASK) == FLASH_IMAGE_TYPE_DATA;
int isRelocLib = (element->CPU & FLASH_IMAGE_TYPE_MASK) == FLASH_IMAGE_TYPE_RELOC_LIB;
printf(" %-3d %-10s %-32s 0x%08x 0x%08x\n", slot,
(isRelocLib ? "[RL]" : (isData ? "[data]" : (isSigDMA ? "[SigDMA]" : ""))),
element->description, element->entryAddress, element->stackAddress);
}
else
{
int isBoot = element->CPU & FLASH_BOOT_FLAG;
printf(" %-3d %3d %-6s %-32s 0x%08x 0x%08x\n", slot, element->CPU & FLASH_CPU_MASK,
(isBoot ? "[boot]" : ""),
element->description, element->entryAddress, element->stackAddress);
}
if (fullOption)
{
printf("\n Section Type Source %-11s Length\n",
(isSigDMA ? "Uncomp Len" : "Destination"));
printf(" ------------------------------------------------------\n");
}
for (j = 0; j < element->numSections; j++, section++)
{
if (fullOption)
{
/*
* Dump all the section info
*/
printf(" %-10d %-9s 0x%08x 0x%08x 0x%08x\n", j, types[section->type],
section->sourceAddress, section->destinationAddress, section->length);
}
/*
* Record this as a used region if it has used some FLASH
*/
if (section->type != SECTION_TYPE_ZERO)
{
char* desc = (char*)malloc(strlen(element->description) + 32);
if (!desc)
{
fprintf(stderr, "flashdir: Out of memory\n");
exit(1);
}
sprintf(desc, "%s (section %d)", element->description, j);
recordRegion(section->sourceAddress, section->length, desc);
}
}
}
/*
* Routine to display the contents of the boot page
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?