📄 restore_ifs.c
字号:
/* * $QNXLicenseC: * Copyright 2007, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software 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 OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ */#include "startup.h"#include "restore_ifs.h"#define RIFS_DEBUG_LEVEL 1// Function prototypesstatic Elf32_Phdr *rifs_readelf(paddr32_t paddr);static int rifs_checksum(void *ptr, long len);static void rifs_init(struct restore_ifs_info *rifs_info);static int check_rifs_signature(struct restore_ifs_info *rifs_info);static int check_ifs_signature(struct image_header *ifs_hdr);struct restore_ifs_info *rifs_info;struct restore_ifs2_info *rifs2_info;unsigned rifs_flag = RIFS_FLAG_NONE;paddr32_t ifs2_paddr_src = 0;paddr32_t ifs2_paddr_dst = 0;unsigned ifs2_size = 0;unsigned mdriver_cksum_max = KILO(500);// Load a secondary (non-bootable) image file systemvoid load_ifs2_nonbootable(void){ // Set the location of IFS2 in RAM if the user didn't specify if(!(rifs_flag & RIFS_FLAG_IFS2_DST)) { // Find a default location to store our 2nd IFS (must by on a 4K page boundary) // NOTE: We assume that the address will be the same everytime. // This should OK since the alloc_ram/find_ram algorithm is deterministic. ifs2_paddr_dst = alloc_ram(NULL_PADDR, ifs2_size, 0x1000); } if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("ifs2_paddr_dst: 0x%X\r\n", ifs2_paddr_dst); } // Attempt to restore IFS2 if it is already in RAM if(!(rifs_flag & RIFS_FLAG_IFS2_RESTORE) || rifs_restore_ifs2() == -1) { // Normal (full) load of the non-bootable secondary IFS rifs_load_ifs2(); }}// Restore a secondary (non-bootable) image files systemint rifs_restore_ifs2(void){ struct image_header *ifs2_hdr; int status = 0; paddr32_t paddr; // Allocate memory for the restore IFS2 info. // NOTE: We assume that the address will be the same everytime. // This should OK since the alloc_ram/find_ram algorithm is deterministic. paddr = alloc_ram(NULL_PADDR, sizeof(struct restore_ifs2_info), sizeof(uint64_t)); rifs2_info = MAKE_1TO1_PTR(paddr); if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("Restore IFS2 searching for valid IFS in RAM...\n"); kprintf("rifs2_info PADDR = 0x%X\n", paddr); kprintf("rifs2_info ADDR = 0x%X\n", rifs2_info); } // Obtain a pointer to the IFS2 that *may* be in RAM. At this point, we still // don't know if it is valid or if it is safe to access this data structure. ifs2_hdr = MAKE_1TO1_PTR(ifs2_paddr_dst); // Determine if there is already an IFS2 in RAM and if the restore // information stored from the last boot is valid. if(check_ifs_signature(ifs2_hdr) == 0 && rifs_checksum(rifs2_info, sizeof(struct restore_ifs2_info)) == 0) { // At this point, we know that the IFS2 signature is valid and the // restore info is valid. We still can't be 100% sure that the IFS is // valid until we peform a checksum on the IFS2. if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("FOUND valid IFS2 signature and RIFS2 info in RAM.\n"); } // Determine if we should checksum the IFS if((rifs_flag & RIFS_FLAG_IFS2_CKSUM)) { // Checksum the entire IFS to make sure it hasn't been corrupted. if(rifs_checksum(ifs2_hdr, rifs2_info->image_size) != 0) { if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("WARNING: Checksum failed on IFS2!\n"); } // Checksum failed - IFS is corrupt status = -1; } } else { if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("WARNING: Skipped IFS2 checksum verification\n"); } } } else { // No IFS2 or invalid restore data status = -1; } if((status == -1) && (debug_flag > RIFS_DEBUG_LEVEL)) { kprintf("Restore IFS2 failed - Reload entire IFS2.\n"); } return(status);}// Load a secondary (non-bootable) image files systemint rifs_load_ifs2(void){ struct image_header *ifs2_hdr; ifs2_hdr = MAKE_1TO1_PTR(ifs2_paddr_dst); // Set the default source location of IFS2 if the user didn't specify if(!(rifs_flag & RIFS_FLAG_IFS2_SRC)) { // Look for 2nd IFS following directly after first IFS ifs2_paddr_src = shdr->imagefs_paddr + shdr->stored_size - shdr->startup_size; } if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("ifs2_paddr_src: 0x%X\r\n", ifs2_paddr_src); kprintf("ifs2_paddr_src (auto): 0x%X\r\n", shdr->imagefs_paddr + shdr->stored_size - shdr->startup_size); } // Reserve space for our 2nd IFS if it is a user specified location if(rifs_flag & RIFS_FLAG_IFS2_DST) { // Address must be on a 4K page boundary (handled by options parsing) alloc_ram(ifs2_paddr_dst, ifs2_size, 0x1000); } // Copy 2nd IFS to RAM copy_memory(ifs2_paddr_dst, ifs2_paddr_src, ifs2_size); // Save the restore info for the next boot with SDRAM in self-refresh if(rifs_flag & RIFS_FLAG_IFS2_RESTORE) { char sig[8] = RIFS_SIGNATURE; int i; // Initialize the signature for(i = 0; i < 8; i++) { rifs2_info->signature[i] = sig[i]; } // Save the image size to be used for the image checksum rifs2_info->image_size = ifs2_hdr->image_size; // Must initialize cksum to 0 before we can calculate cksum on data structure rifs2_info->cksum = 0; // Calculate the restore checksum such that a checksum will result in 0 rifs2_info->cksum = 0xFFFFFFFF & (0x100000000ULL - rifs_checksum(rifs2_info, sizeof(struct restore_ifs2_info))); } return(0);}// Restore an IFS already stored in RAM (i.e. CPU was turned off, RAM was left in self-refresh)int rifs_restore_ifs(paddr32_t ifs_paddr){ paddr32_t paddr_dst, paddr_src; struct image_header *ifs_hdr; int status = 0; int i; paddr32_t paddr; // Allocate memory for the restore ifs info. // NOTE: We assume that the address will be the same everytime. // This should OK since the alloc_ram/find_ram algorithm is deterministic. paddr = alloc_ram(NULL_PADDR, sizeof(struct restore_ifs_info), sizeof(uint64_t)); rifs_info = MAKE_1TO1_PTR(paddr); // Obtain a pointer to the IFS that *may* be in RAM. At this point, we still // don't know if it is valid or if it is safe to access this data structure. ifs_hdr = MAKE_1TO1_PTR(ifs_paddr); if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("Restore IFS searching for valid IFS in RAM...\n"); kprintf("rifs_info PADDR = 0x%X\n", paddr); kprintf("rifs_info ADDR = 0x%X\n", rifs_info); } // Determine if there is already an IFS in RAM and if the restore // information stored from the last boot is valid. if(check_ifs_signature(ifs_hdr) == 0 && check_rifs_signature(rifs_info) == 0) { // At this point, we know that the IFS signature is valid and the // restore info is valid. We still can't be 100% sure that the IFS is // valid until we restore the IFS and peform a checksum. if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("FOUND valid IFS signature and RIFS info in RAM.\n"); kprintf("IFS pre checksum = 0x%X (should not be 0x0)\n", rifs_checksum(ifs_hdr, rifs_info->image_size)); } // Loop through all bootable executables in the image and restore only // the writeable data section to default/original values for(i = 0; i < rifs_info->numboot; i++) { if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("bootable exec %d offset: 0x%X\r\n", i, rifs_info->elfinfo[i].offset); kprintf("bootable exec %d size: 0x%X\r\n", i, rifs_info->elfinfo[i].size); } // Determine location of the executable's data paddr_dst = shdr->image_paddr + shdr->startup_size + rifs_info->elfinfo[i].offset; // Determine if the image is compressed if(shdr->flags1 & STARTUP_HDR_FLAGS1_COMPRESS_MASK) { // Compressed image if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("Compressed image src = 0x%X\n", rifs_info->elfinfo[i].data); } // Copy over the previously saved data (dst & src both in the 1-to-1 mapping region) // NOTE: Use copy_memory to support mini-drivers copy_memory(paddr_dst, rifs_info->elfinfo[i].data, rifs_info->elfinfo[i].size); } else { // IFS in uncompressed, we can take the data directly from the source image paddr_src = shdr->imagefs_paddr + rifs_info->elfinfo[i].offset; if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("Uncompressed image paddr_src = 0x%X\n", paddr_src); } // Copy over data from the original image (dst in the 1-to-1 mapping region, src may be anywhere) copy_memory(paddr_dst, paddr_src, rifs_info->elfinfo[i].size); } } if(debug_flag > RIFS_DEBUG_LEVEL) { kprintf("IFS post checksum = 0x%X (should be 0x0)\n", rifs_checksum(ifs_hdr, rifs_info->image_size)); } // Determine if we should checksum the IFS if((rifs_flag & RIFS_FLAG_CKSUM)) { // Checksum the entire IFS to determine if it has been restored correctly and hasn't been corrupted. if(rifs_checksum(ifs_hdr, rifs_info->image_size) != 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -