/* Create the image package file */ static int pack_images(const char *fip_filename) { int status; uint8_t *fip_base_address; void *entry_address; fip_toc_header_t *toc_header; fip_toc_entry_t *toc_entry; unsigned int entry_index; unsigned int toc_size; unsigned int fip_size; unsigned int entry_offset_address; unsigned int payload_size = 0; /* Validate filename */ if ((fip_filename == NULL) || (strcmp(fip_filename, "") == 0)) { return EINVAL; } /* Payload size calculation */ for (entry_index = 0; entry_index < file_info_count; entry_index++) { payload_size += files[entry_index].size; } /* Allocate memory for entire package, including the final null entry */ toc_size = (sizeof(fip_toc_header_t) + (sizeof(fip_toc_entry_t) * (file_info_count + 1))); fip_size = toc_size + payload_size; fip_base_address = malloc(fip_size); if (fip_base_address == NULL) { printf("Error: Can't allocate enough memory to create package." "Process aborted.\n"); return ENOMEM; } memset(fip_base_address, 0, fip_size); /* Create ToC Header */ toc_header = (fip_toc_header_t *)fip_base_address; toc_header->name = TOC_HEADER_NAME; toc_header->serial_number = TOC_HEADER_SERIAL_NUMBER; toc_header->flags = 0; toc_entry = (fip_toc_entry_t *)(fip_base_address + sizeof(fip_toc_header_t)); /* Calculate the starting address of the first image, right after the * toc header. */ entry_offset_address = toc_size; entry_index = 0; /* Create the package in memory. */ for (entry_index = 0; entry_index < file_info_count; entry_index++) { entry_address = (fip_base_address + entry_offset_address); status = read_file_to_memory(entry_address, &files[entry_index]); if (status != 0) { printf("Error: While reading \"%s\" from filesystem.\n", files[entry_index].filename); return status; } copy_uuid(&toc_entry->uuid, &files[entry_index].name_uuid); toc_entry->offset_address = entry_offset_address; toc_entry->size = files[entry_index].size; toc_entry->flags = 0; entry_offset_address += toc_entry->size; toc_entry++; } /* Add a null uuid entry to mark the end of toc entries */ copy_uuid(&toc_entry->uuid, &uuid_null); toc_entry->offset_address = entry_offset_address; toc_entry->size = 0; toc_entry->flags = 0; /* Save the package to file */ status = write_memory_to_file(fip_base_address, fip_filename, fip_size); if (status != 0) { printf("Error: Failed while writing package to file \"%s\" " "with status=%d.\n", fip_filename, status); return status; } return 0; }
int main(int argc, char *argv[]) { struct core *core; int option; bool enable_memory_dump = false; uint32_t mem_dump_base = 0; uint32_t mem_dump_length = 0; char *mem_dump_filename = NULL; size_t mem_dump_filename_len = 0; bool verbose = false; uint32_t fb_width = 640; uint32_t fb_height = 480; bool block_device_open = false; bool enable_fb_window = false; uint32_t total_threads = 4; char *separator; uint32_t memory_size = 0x1000000; const char *shared_memory_file = NULL; struct stat st; enum { MODE_NORMAL, MODE_COSIMULATION, MODE_GDB_REMOTE_DEBUG } mode = MODE_NORMAL; while ((option = getopt(argc, argv, "f:d:vm:b:t:c:r:s:i:o:")) != -1) { switch (option) { case 'v': verbose = true; break; case 'r': screen_refresh_rate = parse_num_arg(optarg); break; case 'f': enable_fb_window = true; separator = strchr(optarg, 'x'); if (!separator) { fprintf(stderr, "Invalid frame buffer size %s\n", optarg); return 1; } fb_width = parse_num_arg(optarg); fb_height = parse_num_arg(separator + 1); break; case 'm': if (strcmp(optarg, "normal") == 0) mode = MODE_NORMAL; else if (strcmp(optarg, "cosim") == 0) mode = MODE_COSIMULATION; else if (strcmp(optarg, "gdb") == 0) mode = MODE_GDB_REMOTE_DEBUG; else { fprintf(stderr, "Unkown execution mode %s\n", optarg); return 1; } break; case 'd': // Memory dump, of the form: filename,start,length separator = strchr(optarg, ','); if (separator == NULL) { fprintf(stderr, "bad format for memory dump\n"); usage(); return 1; } mem_dump_filename_len = (size_t)(separator - optarg); mem_dump_filename = (char*) malloc(mem_dump_filename_len + 1); strncpy(mem_dump_filename, optarg, mem_dump_filename_len); mem_dump_filename[mem_dump_filename_len] = '\0'; mem_dump_base = parse_num_arg(separator + 1); separator = strchr(separator + 1, ','); if (separator == NULL) { fprintf(stderr, "bad format for memory dump\n"); usage(); return 1; } mem_dump_length = parse_num_arg(separator + 1); enable_memory_dump = true; break; case 'b': if (open_block_device(optarg) < 0) return 1; block_device_open = true; break; case 'c': memory_size = parse_num_arg(optarg); break; case 't': total_threads = parse_num_arg(optarg); if (total_threads < 1 || total_threads > 32) { fprintf(stderr, "Total threads must be between 1 and 32\n"); return 1; } break; case 's': shared_memory_file = optarg; break; case 'i': recv_interrupt_fd = open(optarg, O_RDWR); if (recv_interrupt_fd < 0) { perror("main: failed to open receive interrupt pipe"); return 1; } if (fstat(recv_interrupt_fd, &st) < 0) { perror("main: stat failed on receive interrupt pipe"); return 1; } if ((st.st_mode & S_IFMT) != S_IFIFO) { fprintf(stderr, "%s is not a pipe\n", optarg); return 1; } break; case 'o': send_interrupt_fd = open(optarg, O_RDWR); if (send_interrupt_fd < 0) { perror("main: failed to open send interrupt pipe"); return 1; } if (fstat(send_interrupt_fd, &st) < 0) { perror("main: stat failed on send interrupt pipe"); return 1; } if ((st.st_mode & S_IFMT) != S_IFIFO) { fprintf(stderr, "%s is not a pipe\n", optarg); return 1; } break; case '?': usage(); return 1; } } if (optind == argc) { fprintf(stderr, "No image filename specified\n"); usage(); return 1; } // Don't randomize memory for cosimulation mode, because // memory is checked against the hardware model to ensure a match core = init_core(memory_size, total_threads, mode != MODE_COSIMULATION, shared_memory_file); if (core == NULL) return 1; if (load_hex_file(core, argv[optind]) < 0) { fprintf(stderr, "Error reading image %s\n", argv[optind]); return 1; } if (enable_fb_window) { if (init_frame_buffer(fb_width, fb_height) < 0) return 1; } switch (mode) { case MODE_NORMAL: if (verbose) enable_tracing(core); set_stop_on_fault(core, false); if (enable_fb_window) { while (execute_instructions(core, ALL_THREADS, screen_refresh_rate)) { update_frame_buffer(core); poll_fb_window_event(); check_interrupt_pipe(core); } } else { while (execute_instructions(core, ALL_THREADS, 1000000)) check_interrupt_pipe(core); } break; case MODE_COSIMULATION: set_stop_on_fault(core, false); if (run_cosimulation(core, verbose) < 0) return 1; // Failed break; case MODE_GDB_REMOTE_DEBUG: set_stop_on_fault(core, true); remote_gdb_main_loop(core, enable_fb_window); break; } if (enable_memory_dump) write_memory_to_file(core, mem_dump_filename, mem_dump_base, mem_dump_length); dump_instruction_stats(core); if (block_device_open) close_block_device(); if (stopped_on_fault(core)) return 1; return 0; }