rommd.c 10.5 KB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <netinet/in.h>
#include "os.h"
#include "rcp.h"
#include "os_bb.h"

#define BLOCK_ROUND(x) (((x) + (BB_FL_BLOCK_SIZE-1))&~(BB_FL_BLOCK_SIZE-1))

void dump_pubrom(OSBbLaunchMetaData *md)
{
    OSBbStateVector *sv = &md->state;
    u32 addr = 0;

    if (sv->eepromSize) {
        printf("eeprom=%ld,", sv->eepromSize/128);
        if (!addr) addr = sv->eepromAddress;
    }
    if (sv->flashSize) {
        printf("flash=%ld,", sv->flashSize/128);
        if (!addr) addr = sv->flashAddress;
    }
    if (sv->sramSize) {
        printf("sram=%ld,", sv->sramSize/128);
        if (!addr) addr = sv->sramAddress;
    }
    if (sv->pakSize) {
        int i;
        int count = 0;
        for (i = 0; i < MAXCONTROLLERS; ++i) {
            if (sv->pakAddress[i]) {
                count++;
                if (!addr) addr = sv->pakAddress[i];
            }
        }
        printf("cpak=%d,", count);
    }
    if (addr) {
        printf("address=0x%08lx,", addr);
    }
    if (md->errataSize) {
        printf("errataSize=%ld,errataAddress=0x%08lx,", md->errataSize, md->errataAddress);
    }
    printf("romBase=0x%08lx,", md->romBase);
    printf("tvType=%ld,", md->tvType);
    printf("auxCount=%ld,", md->magic & 0x000000FF);
    printf("memSize=0x%08lx\n", md->memSize);
}

void dump_metadata(OSBbLaunchMetaData *md)
{
    OSBbStateVector *sv = &md->state;
    if (sv->eepromSize)
        printf("EEPROM: %ld bytes @ 0x%08lx\n", sv->eepromSize, sv->eepromAddress);
    if (sv->flashSize)
        printf("flash: %ld bytes @ 0x%08lx\n", sv->flashSize, sv->flashAddress);
    if (sv->sramSize)
        printf("SRAM: %ld bytes @ 0x%08lx\n", sv->sramSize, sv->sramAddress);
    if (sv->pakSize) {
        int i;
        for (i = 0; i < MAXCONTROLLERS; ++i) {
            printf("CP%d: %ld bytes @ 0x%08lx\n", i+1, sv->pakSize, sv->pakAddress[i]);
        }
    }
    printf("romBase: 0x%08lx\n", md->romBase);
    printf("tvType: %ld\n", md->tvType);
    printf("memSize: 0x%08lx\n", md->memSize);
    if (md->errataSize)
        printf("errata: %ld bytes @ 0x%08lx\n", md->errataSize, md->errataAddress);
    printf("auxCount: %ld\n", md->magic & 0x000000FF);
}

void swap_metadata(OSBbLaunchMetaData *md)
{
    u32 *p = (u32 *)md;
    int i;

    for (i = 0; i < sizeof(OSBbLaunchMetaData); i+=4) {
        *p = ntohl(*p);
        ++p;
    }
}

void Usage(char *prog)
{
    fprintf(stderr, "Usage: %s [options] <romfile>\n", prog);
    fprintf(stderr,
            "\t -a, --addr <a>    Set base address for allocations\n"
            "\t -e, --eeprom <n>  Allocate 'n' Kb for EEPROM (0, 4, or 16).\n"
            "\t -f, --flash <n>   Allocate 'n' Kb for flash (0 or 1024).\n"
            "\t -s, --sram <n>    Allocate 'n' Kb for SRAM (0 or 256).\n"
            "\t -c, --cp <n>      Allocate 32Kb for each of 'n' controller paks.\n"
            "\t -t, --tv <type>   Set the TV type to 'n' (0=PAL, 1=NTSC, 2=MPAL).\n"
            "\t -r, --rombase <b> Set the rom base address to 'b'.\n"
            "\t -m, --memsize <m> Set the memory size to 'm' MB.\n"
            "\t -S, --errataSize <n> Set the errata size to 'n' KB.\n"
            "\t -A, --errataAddr <a> Set the errata address.\n"
            "\t     --errata      Use standard errata size and address (16KB @ 0x807bc000).\n"
            "\t -u, --auxCount <n> Set the number of u0x files to 'n' (0, 1, 2, 3 or 4).\n"
            "\t -h, --help        Print this message and exit.\n"
           );
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
    static struct option long_options[] = {
        {"addr", 1, 0, 'a'},
        {"cp", 1, 0, 'c'},
        {"eeprom", 1, 0, 'e'},
        {"errataSize", 1, 0, 'S'},
        {"errataAddr", 1, 0, 'A'},
        {"errata", 0, 0, 0},
        {"flash", 1, 0, 'f'},
        {"memsize", 1, 0, 'm'},
        {"pubrom", 0, 0, 'p'},
        {"rombase", 1, 0, 'r'},
        {"sram", 1, 0, 's'},
        {"tv", 1, 0, 't'},
        {"auxCount", 1, 0, 'u'},
        {0, 0, 0, 0}
    };
    static char *short_options = "a:c:e:f:hm:pr:s:t:u:A:S:";
    OSBbLaunchMetaData md;
    OSBbStateVector *sv = &md.state;
    FILE *fp = NULL;
    int eeprom = -1;
    int sram = -1;
    int flash = -1;
    int cp = -1;
    int tvType = -1;
    u32 romBase = 0;
    u32 memSize = 0;
    u32 addr = 0x807c0000;
    u32 errataAddr = 0;
    u32 errataSize = 0;
    int auxCount = -1;
    int i, changed = 0;
    int long_index;
    int size = 0, padded = 0;
    int pubrom = 0;

    while (1) {
        int c;
        if ((c = getopt_long(argc, argv, short_options, long_options, &long_index)) == -1) {
            break;
        }
        switch(c) {
        case 0:
            if (!strcmp("errata", long_options[long_index].name)) {
                errataAddr = 0x807bc000;
                errataSize = 16384;
                changed = 1;
            }
            break;
        case 'a':
            addr = strtoul(optarg, NULL, 0);
            changed = 1;
            break;
        case 'A':
            errataAddr = strtoul(optarg, NULL, 0);
            changed = 1;
            break;
        case 'S':
            errataSize = strtoul(optarg, NULL, 0);
            changed = 1;
            break;
        case 'c':
            cp = strtol(optarg, NULL, 0);
            if (cp < 0 || cp > MAXCONTROLLERS) {
                fprintf(stderr, "Only 0-%d controller paks are supported\n", MAXCONTROLLERS);
                Usage(argv[0]);
            }
            changed = 1;
            break;
        case 'e':
            eeprom = strtol(optarg, NULL, 0);
            if (eeprom != 0 && eeprom != 4 && eeprom != 16) {
                fprintf(stderr, "The EEPROM must be 0, 4, or 16 Kb\n");
                Usage(argv[0]);
            }
            changed = 1;
            break;
        case 'f':
            flash = strtol(optarg, NULL, 0);
            if (flash != 0 && flash != 1024) {
                fprintf(stderr, "The flash must be 0, or 1024 Kb\n");
                Usage(argv[0]);
            }
            changed = 1;
            break;
        case 'h':
            Usage(argv[0]);
            break;
        case 'm':
            memSize = strtol(optarg, NULL, 0);
            if (memSize != 4 && memSize != 8) {
                fprintf(stderr, "memsize must be either 4 or 8 MB\n");
                Usage(argv[0]);
            }
            memSize *= 0x100000;
            changed = 1;
            break;
        case 'p':
            pubrom = 1;
            break;
        case 'r':
            romBase = strtoul(optarg, NULL, 0);
            changed = 1;
            break;
        case 's':
            sram = strtol(optarg, NULL, 0);
            if (sram != 0 && sram != 256) {
                fprintf(stderr, "The SRAM must be 0 or 256 Kb\n");
                Usage(argv[0]);
            }
            changed = 1;
            break;
        case 't':
            tvType = strtol(optarg, NULL, 0);
            if (tvType < 0 || tvType > 2) {
                fprintf(stderr, "TV type must be 0, 1, or 2\n");
                Usage(argv[0]);
            }
            changed = 1;
            break;
        case 'u':
            auxCount = strtol(optarg, NULL, 0);
            if (auxCount < 0 || auxCount > 4) {
                fprintf(stderr, "number of u0x files should be between 0 - 4\n");
                Usage(argv[0]);
            }
            changed = 1;
            break;
        default:
            fprintf(stderr, "Illegal option '%c'\n", c);
            break;
        }
    }
    if (argc != (optind+1)) {
        fprintf(stderr, "You must specify a rom file.\n");
        Usage(argv[0]);
    }

    if ((fp = fopen(argv[optind], "r+")) == NULL) {
        perror(argv[optind]);
        return -1;
    }

    if (fseek(fp, -sizeof(md), SEEK_END) < 0) {
        perror("fseek");
        return -1;
    }

    if (fread(&md, sizeof(md), 1, fp) != 1) {
        fprintf(stderr, "Unable to read last %d bytes of '%s'\n", sizeof(md), argv[optind]);
        return -1;
    }
    size = ftell(fp);
    padded = (size + (BB_FL_BLOCK_SIZE-1)) & ~(BB_FL_BLOCK_SIZE-1);

    swap_metadata(&md);

    if ((md.magic & 0xFFFFFF00) != BB_METADATA_MAGIC) {
        if (changed || pubrom) {
            /* Default values */
            bzero(&md, sizeof(md));
            md.magic = BB_METADATA_MAGIC;
            md.memSize = 0x00400000;
            md.tvType = OS_TV_NTSC;
            md.romBase = PHYS_TO_K1(PI_DOM1_ADDR2);
            size = (padded - size < sizeof(md)) ? padded + BB_FL_BLOCK_SIZE : padded;
        } else {
            fprintf(stderr, "'%s' has no metadata\n", argv[optind]);
            return -1;
        }
    }

    if (sv->eepromAddress)
        addr = sv->eepromAddress;
    else if (sv->flashAddress)
        addr = sv->flashAddress;
    else if (sv->sramAddress)
        addr = sv->sramAddress;
    else if (sv->pakAddress[0])
        addr = sv->pakAddress[0];

    if (eeprom != -1) {
        sv->eepromSize = eeprom * 128;
    }
    if (sv->eepromSize) {
        sv->eepromAddress = addr;
        addr += BLOCK_ROUND(sv->eepromSize);
    }

    if (flash != -1) {
        sv->flashSize = flash * 128;
    }
    if (sv->flashSize) {
        sv->flashAddress = addr;
        addr += BLOCK_ROUND(sv->flashSize);
    }

    if (sram != -1) {
        sv->sramSize = sram * 128;
    }
    if (sv->sramSize) {
        sv->sramAddress = addr;
        addr += BLOCK_ROUND(sv->sramSize);
    }

    if (cp != -1) {
        sv->pakSize = cp ? 32 * 1024 : 0;
    } else {
        cp = 0;
        for (i = 0; i < MAXCONTROLLERS; ++i) {
            cp += (sv->pakAddress[i] != 0);
        }
    }

    for (i = 0; i < cp; ++i) {
        sv->pakAddress[i] = addr;
        addr += BLOCK_ROUND(sv->pakSize);
    }
    for (; i < MAXCONTROLLERS; ++i) {
        sv->pakAddress[i] = 0;
    }

    if (tvType != -1) {
        md.tvType = tvType;
    }

    if (memSize) {
        md.memSize = memSize;
    }

    if (romBase) {
        md.romBase = romBase;
    }

    if (errataSize) {
        md.errataSize = errataSize;
        md.errataAddress = errataAddr;
    }
    
    if (auxCount != -1)
        md.magic = BB_METADATA_MAGIC | auxCount;
   
    if (pubrom) {
        dump_pubrom(&md);
    } else {
        dump_metadata(&md);
    }

    if (changed) {
        swap_metadata(&md);

        if (fseek(fp, size-sizeof(md), SEEK_SET) < 0) {
            perror("fseek");
            return -1;
        }

        if (fwrite(&md, sizeof(md), 1, fp) != 1) {
            fprintf(stderr, "Unable to write last %d bytes of '%s'\n", sizeof(md), argv[optind]);
            return -1;
        }
    }

    if (fp) fclose(fp);
    return 0;
}