📄 flasher.c
字号:
imageInfo = &header.imageInfo;
/*
* Perform some simple sanity checks.
*/
if ((imageInfo->CPU & FLASH_CPU_MASK) >= FLASH_MAX_CPUS)
{
fprintf(stderr, "flasher: Invalid CPU number for bootstrap in %s\n", image->fileName);
exit(1);
}
/*
* A bootstrap should be 1 or more sections. The 1st one should be a SKIP
* section, and any others should be relocation information. Another SKIP
* section can be ignored.
*/
if (imageInfo->numSections >= 1)
{
if ((imageInfo->sections[0].type & SECTION_TYPE_MASK) != SECTION_TYPE_SKIP)
{
fprintf(stderr, "flasher: Invalid bootstrap in %s\n", image->fileName);
exit(1);
}
if (imageInfo->numSections > 1)
{
if ((imageInfo->sections[0].type & PLACEMENT_TYPE_MASK) != PLACEMENT_TYPE_ANYWHERE)
{
fprintf(stderr, "flasher: Invalid bootstrap in %s\n", image->fileName);
exit(1);
}
}
}
else
{
fprintf(stderr, "flasher: Invalid number of bootstrap sections in %s (%d < 1)\n",
image->fileName, imageInfo->numSections);
exit(1);
}
fseek(fp, -sizeof(imageSection_t), SEEK_CUR);
imageSections = allocate(sizeof(imageSection_t) * imageInfo->numSections);
if (fread(imageSections, sizeof(imageSection_t) * imageInfo->numSections, 1, fp) != 1)
{
fprintf(stderr, "flasher: Failed to read sections from %s\n", image->fileName);
exit(1);
}
for (i = 1; i < imageInfo->numSections; i++)
{
switch (imageSections[i].type & SECTION_TYPE_MASK)
{
case SECTION_TYPE_SYMBOLS:
case SECTION_TYPE_RELOCATIONS:
break;
case SECTION_TYPE_SKIP:
/* If we see another skip section, pretend it isn't there */
imageInfo->numSections--;
break;
default:
fprintf(stderr, "flasher: Invalid bootstrap in %s\n", image->fileName);
exit(1);
}
}
/*
* Check the section we've got is appropriate for this phase of placement. If
* not, do nothing.
*/
if (phase == 0)
{
if ((imageSections[0].type & PLACEMENT_TYPE_MASK) == PLACEMENT_TYPE_ANYWHERE)
{
free(imageSections);
fclose(fp);
return;
}
}
else
{
if ((imageSections[0].type & PLACEMENT_TYPE_MASK) != PLACEMENT_TYPE_ANYWHERE)
{
free(imageSections);
fclose(fp);
return;
}
}
printf("Placing bootstrap for CPU %d (%s)\n", imageInfo->CPU & FLASH_CPU_MASK, imageInfo->description);
/*
* Create a buffer to represent this update, and read in the image.
*/
update = (buffer_t*)allocate(sizeof(buffer_t));
update->info.data = (unsigned char*)allocate(imageSections[0].length);
update->length = imageSections[0].length;
if (fread(update->info.data, imageSections[0].length, 1, fp) != 1)
{
fprintf(stderr, "flasher: Failed to read section data from %s\n", image->fileName);
exit(1);
}
/*
* Also read in any relocation data.
*/
if (imageInfo->numSections > 1)
{
relocInfo = (buffer_t*)allocate(sizeof(buffer_t) * (imageInfo->numSections - 1));
for (i = 1; i < imageInfo->numSections; i++)
{
relocInfo[i - 1].info.data = (unsigned char*)allocate(imageSections[i].length);
relocInfo[i - 1].length = imageSections[i].length;
if (fread(relocInfo[i - 1].info.data, relocInfo[i - 1].length, 1, fp) != 1)
{
fprintf(stderr, "flasher: Failed to read relocations from %s\n", image->fileName);
exit(1);
}
}
}
fclose(fp);
/*
* If the bootstrap was already in use, free off the memory it was using, and
* then allocate the new lot.
*/
if (bootPages->bootStrapDescriptors[imageInfo->CPU & FLASH_CPU_MASK].startAddress &&
bootPages->bootStrapDescriptors[imageInfo->CPU & FLASH_CPU_MASK].length)
{
buffer = (buffer_t*)allocate(sizeof(buffer_t));
buffer->address = (unsigned int)(bootPages->bootStrapDescriptors[imageInfo->CPU & FLASH_CPU_MASK].startAddress);
buffer->length = bootPages->bootStrapDescriptors[imageInfo->CPU & FLASH_CPU_MASK].length;
buffer->info.type = MEM_FREE;
updateMemMap(buffer, &flashMap);
}
buffer = (buffer_t*)allocate(sizeof(buffer_t));
/*
* The section must be type INPLACE, or preferably PIC, so we can place it
* where ever we want.
* We align 'anywhere' blocks on MIN_SECTION_ALIGNMENT byte boundaries.
*/
switch (imageSections[0].type & PLACEMENT_TYPE_MASK)
{
case PLACEMENT_TYPE_ANYWHERE:
buffer->address = findBestFree(imageSections[0].length, MIN_SECTION_ALIGNMENT,
&flashMap, (unsigned int) bootPages->imageControlDirectoryPtr);
break;
case PLACEMENT_TYPE_INPLACE:
buffer->address = (unsigned int)(imageSections[0].sourceAddress);
break;
default:
fprintf(stderr, "flasher: Unsupported bootstrap placement type in %s\n", image->fileName);
exit(1);
break;
}
buffer->length = imageSections[0].length;
buffer->info.type = MEM_USED;
bootStrapAddress = buffer->address;
updateMemMap(buffer, &flashMap);
/*
* Record this update request.
*/
update->address = bootStrapAddress;
addBuffer(update, &updateList);
/*
* Process any relocations we need to do also.
*/
if (relocInfo)
{
buffer_t* relocs = NULL;
buffer_t* symbs = NULL;
for (i = 1; i < imageInfo->numSections; i++)
{
unsigned int type = imageSections[i].type & SECTION_TYPE_MASK;
if (type == SECTION_TYPE_SYMBOLS)
{
symbs = &relocInfo[i - 1];
}
else if (type == SECTION_TYPE_RELOCATIONS)
{
relocs = &relocInfo[i - 1];
}
}
if (symbs && relocs)
processElfRelocs(update->info.data,
bootStrapAddress,
imageInfo->CPU & FLASH_CPU_ARCH_MASK,
(reloc_t*)relocs->info.data,
relocs->length / sizeof(reloc_t),
(symb_t*)(symbs ? symbs->info.data : NULL),
(symbs ? symbs->length : 0) / sizeof(symb_t));
}
/*
* Update the boot descriptor for this CPU.
*/
bootPages->bootStrapDescriptors[imageInfo->CPU & FLASH_CPU_MASK].startAddress = bootStrapAddress;
bootPages->bootStrapDescriptors[imageInfo->CPU & FLASH_CPU_MASK].length = imageSections[0].length;
strncpy(bootPages->bootStrapDescriptors[imageInfo->CPU & FLASH_CPU_MASK].description,
imageInfo->description, FLASH_DESC_LEN);
free(imageSections);
free(relocInfo);
}
/*
* Routine used to delete a slot from the image directory.
* It frees up the memory in the FLASH that the image there was using.
*/
static void deleteSlot(int slot, bootPages_t* bootPages, imageDirectoryPages_t* imageDirectoryPages)
{
imageControl_t* entry;
imageSection_t* sections;
buffer_t* buffer;
int i;
if (slot != FAILSAFE_SLOT)
{
/*
* We've been asked to delete this slot - if its already free, we're done.
*/
if (!imageDirectoryPages->directory.entries[slot])
{
return;
}
entry = imageDirectoryPages->directory.entries[slot];
sections = entry->sections;
/*
* This slot is now free.
*/
imageDirectoryPages->directory.entries[slot] = 0;
/*
* Free off the sections used by this image.
*/
for (i = 0; i < entry->numSections; i++)
{
if (sections[i].type != SECTION_TYPE_ZERO)
{
buffer = (buffer_t*)allocate(sizeof(buffer_t));
buffer->address = (unsigned int)(sections[i].sourceAddress);
buffer->length = sections[i].length;
buffer->info.type = MEM_FREE;
updateMemMap(buffer, &flashMap);
}
}
/*
* Free off the control info too.
*/
buffer = (buffer_t*)allocate(sizeof(buffer_t));
buffer->address = (unsigned int)&entry;
buffer->length = sizeof(imageControl_t) + (entry->numSections - 1) * sizeof(imageSection_t);
buffer->info.type = MEM_FREE;
updateMemMap(buffer, &controlMap);
}
else
{
/*
* Deleting the failsafe image slot.
*/
entry = &bootPages->failsafeImageControlStructure;
sections = entry->sections;
/*
* This slot is now free.
*/
*((unsigned int*)&bootPages->failsafeImageControlStructure) = 0xFFFFFFFF;
}
}
/*
* Routine to scan the image directory, and ensure that at least one image per
* CPU is marked as the boot image. If non is marked, we pick the first one we
* found.
*/
static void checkBootableImages(imageDirectoryPages_t* imageDirectoryPages)
{
unsigned int cpu;
imageControl_t* controlStruct;
int i;
int firstFound;
int bootSlot;
/*
* For each possible CPU, scan the table looking for images.
* If we find no boot images, and there is at least one image present for that
* CPU, make that first image found the boot image for it.
*/
for (cpu = 0; cpu < FLASH_MAX_CPUS; cpu++)
{
firstFound = -1;
bootSlot = -1;
for (i = 0; i < FLASH_IMAGE_DIRECTORY_SIZE; i++)
{
controlStruct = imageDirectoryPages->directory.entries[i];
if (controlStruct && ((controlStruct->CPU & FLASH_CPU_MASK) == cpu) &&
!(controlStruct->CPU & FLASH_IMAGE_TYPE_MASK)
)
{
if (firstFound == -1)
{
firstFound = i;
}
if (controlStruct->CPU & FLASH_BOOT_FLAG)
{
if (bootSlot == -1)
{
bootSlot = i;
}
else
{
fprintf(stderr, "flasher: Internal error: > 1 boot slot for cpu %d found\n", cpu);
exit(1);
}
}
}
}
/*
* If no boot slot found, pick the first one
*/
if ((bootSlot == -1) && (firstFound != -1))
{
controlStruct = imageDirectoryPages->directory.entries[firstFound];
controlStruct->CPU |= FLASH_BOOT_FLAG;
printf("Set image '%s' in slot %d to be a boot image\n", controlStruct->description, firstFound);
}
}
}
/*
* Routine used by determineProgramming() to process a new user image.
*/
static void processImage(image_t* image, bootPages_t* bootPages, imageDirectoryPages_t* imageDirectoryPages,
int phase, flashDevice_t** devices, flashTarget_t* target)
{
int section;
FILE* fp;
fileHeader_t header;
imageControl_t* imageInfo;
imageControl_t* controlStruct;
imageSection_t* imageSections;
size_t entrySize;
buffer_t* allocBlock;
int rlImage = 0;
int st40Image = 0;
/*
* The user can specify a slot to use, or ask us to pick one.
* Do this on the initial phase only.
*/
if (phase == 0)
{
if (image->slot == ANY_SLOT)
{
int slot;
/*
* Find a spare slot.
*/
for (slot = 0; slot < FLASH_IMAGE_DIRECTORY_SIZE; slot++)
{
if (imageDirectoryPages->directory.entries[slot] == NULL)
{
break;
}
}
if (slot == FLASH_IMAGE_DIRECTORY_SIZE)
{
fprintf(stderr, "flasher: No spare image slots\n");
exit(1);
}
image->slot = slot;
/* We just make sure it's non-zero for now - the correct address will be
* filled in later.
*/
imageDirectoryPages->directory.entries[slot] = (imageControl_t*)&slot;
}
else
{
/*
* Free up the FLASH used by the image there already
*/
deleteSlot(image->slot, bootPages, imageDirectoryPages);
}
}
/*
* 'image->slot' is the one we'll use, so we need to find:
* - room for the boot control structure in the image directory
* - room for the image itself in the rest of the FLASH
*
* Open up the image file.
*/
if (!(fp = fopen(image->fileName, "rb")))
{
fprintf(stderr, "flasher: Failed to open %s\n", image->fileName);
exit(1);
}
/*
* Read in the header.
*/
if (fread(&header, sizeof(header), 1, fp) != 1)
{
fprintf(stderr, "flasher: Failed to read header from %s\n", image->fileName);
exit(1);
}
/*
* Check it is sane.
*/
if (header.magic != IMAGE_FILE_MAGIC)
{
fprintf(stderr, "flasher: Invalid image in %s\n", image->fileName);
exit(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -