/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id:$ * * Copyright (C) 2010 by Marcin Bukat * * code taken mostly from mkboot.c * Copyright (C) 2005 by Linus Nielsen Feltzing * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include #include #include #include "mkmpioboot.h" #define OF_FIRMWARE_LEN 0x100000 /* size of the OF file */ #define MPIO_STRING_OFFSET 0xfffe0 /* offset of the version string in OF */ #define BOOTLOADER_MAX_SIZE 0x1f800 /* free space size */ /* Descriptive name of these models */ static const char* model_names[] = { [MODEL_HD200] = "MPIO HD200", [MODEL_HD300] = "MPIO HD300", }; /* Model names used in the Rockbox header in ".mpio" files - these match the -add parameter to the "scramble" tool */ static const char* rb_model_names[] = { [MODEL_HD200] = "hd20", [MODEL_HD300] = "hd30", }; /* Model numbers used to initialise the checksum in the Rockbox header in ".mpio" files - these are the same as MODEL_NUMBER in config-target.h */ static const int rb_model_num[] = { [MODEL_HD200] = 69, [MODEL_HD300] = 70, }; /* Strings which indentify OF version */ static const char* of_model_string[] = { [MODEL_HD200] = "HD200 HDD Audio Ver113005", [MODEL_HD300] = "HD300 HDD Audio Ver113006", }; /* MPIO HD200 and HD300 firmware is plain binary image * 4 bytes of initial SP (loaded on reset) * 4 bytes of initial PC (loaded on reset) * binary image with entry point 0x00000008 * * We put our bootloader code at 0x000e0000 * and patch reset vector to jump directly * into our code on reset */ static unsigned char image[OF_FIRMWARE_LEN]; static unsigned int get_uint32be(unsigned char* p) { return ((p[0] << 24) | (p[1] << 16) | (p[2]<<8) | p[3]); } static long checksum(unsigned char* buf, int model, unsigned long length) { unsigned long chksum = model; unsigned long i; if(buf == NULL) return -1; for (i = 0; i < length; i++) { chksum += *buf++; } return chksum; } int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin) { FILE *f; int i; int len; int model_index; unsigned long file_checksum; unsigned char header[8]; memset(image, 0xff, sizeof(image)); /* First, read the mpio original firmware into the image */ f = fopen(infile, "rb"); if(!f) { fprintf(stderr, "[ERR] Can not open %s file for reading\n", infile); return -1; } i = fread(image, 1, OF_FIRMWARE_LEN, f); if(i < OF_FIRMWARE_LEN) { fprintf(stderr, "[ERR] %s file read error\n", infile); fclose(f); return -2; } fclose(f); /* Now check if we have OF file loaded based on presence * of the version string in firmware */ for(model_index = 0; model_index < NUM_MODELS; model_index++) if (strcmp(of_model_string[model_index], (char*)(image + MPIO_STRING_OFFSET)) == 0) break; if(model_index == NUM_MODELS) { fprintf(stderr, "[ERR] Unknown MPIO original firmware version\n"); return -3; } fprintf(stderr, "[INFO] Loading original firmware file for %s\n", model_names[model_index]); /* Now, read the boot loader into the image */ f = fopen(bootfile, "rb"); if(!f) { fprintf(stderr, "[ERR] Can not open %s file for reading\n", bootfile); return -4; } fprintf(stderr, "[INFO] Loading Rockbox bootloader file\n"); /* get bootloader size * excluding header */ fseek(f, 0, SEEK_END); len = ftell(f) - 8; if (len > BOOTLOADER_MAX_SIZE) { fprintf(stderr, "[ERR] Bootloader doesn't fit in firmware file.\n"); fprintf(stderr, "[ERR] This bootloader is %d bytes long\n", len); fprintf(stderr, "[ERR] and maximum allowed size is %d bytes\n", BOOTLOADER_MAX_SIZE); return -5; } /* Now check if the place we want to put * our bootloader is free */ for(i=0;i