Search
lxdream.org :: lxdream/src/bootstrap.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/bootstrap.c
changeset 1099:566cdeb157ec
prev1095:a8b798030464
author nkeynes
date Sun Feb 12 16:30:26 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Add -Werror for mregparm check, so it actually fails if mregparm isn't
accepted
file annotate diff log raw
nkeynes@26
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@26
     3
 *
nkeynes@26
     4
 * CD Bootstrap header parsing. Mostly for informational purposes.
nkeynes@26
     5
 *
nkeynes@26
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@26
     7
 *
nkeynes@26
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@26
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@26
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@26
    11
 * (at your option) any later version.
nkeynes@26
    12
 *
nkeynes@26
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@26
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@26
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@26
    16
 * GNU General Public License for more details.
nkeynes@26
    17
 */
nkeynes@1
    18
nkeynes@26
    19
#include "dream.h"
nkeynes@26
    20
#include "bootstrap.h"
nkeynes@26
    21
nkeynes@1
    22
static uint32_t compute_crc16( dc_bootstrap_head_t h )
nkeynes@1
    23
{
nkeynes@1
    24
    /* Note: Algorithm taken from http://mc.pp.se/dc/ip0000.bin.html */
nkeynes@1
    25
    uint32_t i, c, n = 0xffff;
nkeynes@1
    26
    char *data = h->product_id;
nkeynes@1
    27
    for (i = 0; i < 16; i++)
nkeynes@1
    28
    {
nkeynes@1
    29
        n ^= (data[i]<<8);
nkeynes@1
    30
        for (c = 0; c < 8; c++)
nkeynes@1
    31
            if (n & 0x8000)
nkeynes@1
    32
                n = (n << 1) ^ 4129;
nkeynes@1
    33
            else
nkeynes@1
    34
                n = (n << 1);
nkeynes@1
    35
    }
nkeynes@1
    36
    return n & 0xffff;
nkeynes@1
    37
}
nkeynes@1
    38
nkeynes@26
    39
nkeynes@26
    40
static char *dc_peripherals[] = { "Uses WinCE", "Unknown (0x0000002)",
nkeynes@736
    41
        "Unknown (0x0000004)", "Unknown (0x0000008)",
nkeynes@736
    42
        "VGA Box", "Unknown (0x0000020)",
nkeynes@736
    43
        "Unknown (0x0000040)", "Unknown (0x0000080)",
nkeynes@736
    44
        "Other Expansions", "Puru Puru pack",
nkeynes@736
    45
        "Mike", "Memory card",
nkeynes@736
    46
        "Basic controller", "C button",
nkeynes@736
    47
        "D button", "X button",
nkeynes@736
    48
        "Y button", "Z button",
nkeynes@736
    49
        "Expanded direction buttons",
nkeynes@736
    50
        "Analog R trigger", "Analog L trigger",
nkeynes@736
    51
        "Analog horizontal", "Analog vertical",
nkeynes@736
    52
        "Expanded analog horizontal",
nkeynes@736
    53
        "Expanded analog vertical",
nkeynes@736
    54
        "Gun", "Keyboard", "Mouse" };
nkeynes@26
    55
nkeynes@26
    56
nkeynes@26
    57
/* Expansion units */
nkeynes@26
    58
#define DC_PERIPH_WINCE    0x0000001
nkeynes@26
    59
#define DC_PERIPH_VGABOX   0x0000010
nkeynes@26
    60
#define DC_PERIPH_OTHER    0x0000100
nkeynes@26
    61
#define DC_PERIPH_PURUPURU 0x0000200
nkeynes@26
    62
#define DC_PERIPH_MIKE     0x0000400
nkeynes@26
    63
#define DC_PERIPH_MEMCARD  0x0000800
nkeynes@26
    64
/* Basic requirements */
nkeynes@26
    65
#define DC_PERIPH_BASIC    0x0001000 /* Basic controls - start, a, b, arrows */
nkeynes@26
    66
#define DC_PERIPH_C_BUTTON 0x0002000
nkeynes@26
    67
#define DC_PERIPH_D_BUTTON 0x0004000
nkeynes@26
    68
#define DC_PERIPH_X_BUTTON 0x0008000
nkeynes@26
    69
#define DC_PERIPH_Y_BUTTON 0x0010000
nkeynes@26
    70
#define DC_PERIPH_Z_BUTTON 0x0020000
nkeynes@26
    71
#define DC_PERIPH_EXP_DIR  0x0040000 /* Expanded direction buttons */
nkeynes@26
    72
#define DC_PERIPH_ANALOG_R 0x0080000 /* Analog R trigger */
nkeynes@26
    73
#define DC_PERIPH_ANALOG_L 0x0100000 /* Analog L trigger */
nkeynes@26
    74
#define DC_PERIPH_ANALOG_H 0x0200000 /* Analog horizontal controller */
nkeynes@26
    75
#define DC_PERIPH_ANALOG_V 0x0400000 /* Analog vertical controller */
nkeynes@26
    76
#define DC_PERIPH_EXP_AH   0x0800000 /* Expanded analog horizontal (?) */
nkeynes@26
    77
#define DC_PERIPH_EXP_AV   0x1000000 /* Expanded analog vertical (?) */
nkeynes@26
    78
/* Optional peripherals */
nkeynes@26
    79
#define DC_PERIPH_GUN      0x2000000
nkeynes@26
    80
#define DC_PERIPH_KEYBOARD 0x4000000
nkeynes@26
    81
#define DC_PERIPH_MOUSE    0x8000000
nkeynes@26
    82
nkeynes@26
    83
/**
nkeynes@26
    84
 * Dump the bootstrap info to the output log for infomational/debugging
nkeynes@26
    85
 * purposes.
nkeynes@167
    86
 * @param detail true to include a ful information dump, false for just
nkeynes@167
    87
 *  the facts, maam.
nkeynes@26
    88
 */
nkeynes@502
    89
void bootstrap_dump( void *data, gboolean detail )
nkeynes@1
    90
{
nkeynes@1
    91
    struct dc_bootstrap_head *head;
nkeynes@1
    92
    int i, got, periph, crc, hcrc;
nkeynes@1
    93
    char *prot_symbols;
nkeynes@1
    94
    char buf[512];
nkeynes@1
    95
nkeynes@1
    96
    /* Dump out the bootstrap metadata table */
nkeynes@1
    97
    head = (struct dc_bootstrap_head *)data;
nkeynes@1
    98
    prot_symbols = ((char *)data) + 0x3700;
nkeynes@1
    99
    memcpy( buf, head->product_name, 128 );
nkeynes@1
   100
    for( i=127; i>0 && buf[i] == ' '; i-- );
nkeynes@1
   101
    buf[i] = '\0';
nkeynes@1
   102
    periph = strtol( head->peripherals, NULL, 16 );
nkeynes@167
   103
    INFO( "Name: %s   Author: %-16.16s",
nkeynes@1
   104
          buf, head->vendor_id );
nkeynes@1
   105
    sprintf( buf, "%4.4s", head->crc );
nkeynes@1
   106
    crc = compute_crc16(head);
nkeynes@1
   107
    hcrc = strtol( buf, NULL, 16 );
nkeynes@1
   108
    INFO( "  Product ID:   %-10.10s   Product Ver: %-6.6s   Date: %-8.8s",
nkeynes@1
   109
          head->product_id, head->product_ver, head->product_date );
nkeynes@167
   110
    if( detail ) {
nkeynes@736
   111
        INFO( "  Header CRC:   %04X (Computed %04X)", hcrc, crc );
nkeynes@736
   112
        INFO( "  Boot File:    %-16.16s", head->boot_file );
nkeynes@736
   113
        INFO( "  Disc ID:      %-11.11s  Regions:      %-8.8s   Peripherals: %07X",
nkeynes@736
   114
              head->gdrom_id, head->regions, periph );
nkeynes@736
   115
        strcpy( buf, "     Supports: " );
nkeynes@736
   116
        got = 0;
nkeynes@736
   117
        for( i=0; i<28; i++ ) {
nkeynes@736
   118
            if( periph & (1<<i) ){
nkeynes@736
   119
                if( got ) strcat( buf, ", " );
nkeynes@736
   120
                strcat( buf, dc_peripherals[i] );
nkeynes@736
   121
                got = 1;
nkeynes@736
   122
            }
nkeynes@736
   123
            if( i == 11 ) i = 23; /* Skip 8-23 */
nkeynes@736
   124
        }
nkeynes@736
   125
        INFO( buf, NULL );
nkeynes@736
   126
        strcpy( buf, "     Requires: " );
nkeynes@736
   127
        got = 0;
nkeynes@736
   128
        for( i=12; i<24; i++ ) {
nkeynes@736
   129
            if( periph & (1<<i) ) {
nkeynes@736
   130
                if( got ) strcat( buf, ", " );
nkeynes@736
   131
                strcat( buf, dc_peripherals[i] );
nkeynes@736
   132
                got = 1;
nkeynes@736
   133
            }
nkeynes@736
   134
        }
nkeynes@736
   135
        INFO( buf, NULL );
nkeynes@1
   136
    }
nkeynes@1
   137
}
nkeynes@1099
   138
nkeynes@1099
   139
/* Scramble/unscramble, based on Marcus Comstedt's algorithm. */
nkeynes@1099
   140
nkeynes@1099
   141
typedef uint16_t randseed;
nkeynes@1099
   142
nkeynes@1099
   143
#define MAXBLOCK (2048*1024)
nkeynes@1099
   144
#define CHUNKSIZE 32
nkeynes@1099
   145
#define NEXT(seed)  (((seed = (seed*2109+9273)&0x7fff) + 0xC000) & 0xFFFF)
nkeynes@1099
   146
nkeynes@1099
   147
void bootprogram_scramble( unsigned char *dest, unsigned char *src, size_t length )
nkeynes@1099
   148
{
nkeynes@1099
   149
    randseed seed = length & 0xFFFF;
nkeynes@1099
   150
    unsigned table[MAXBLOCK/32];
nkeynes@1099
   151
    unsigned char *s = src;
nkeynes@1099
   152
    unsigned char *d = dest;
nkeynes@1099
   153
nkeynes@1099
   154
    for( unsigned blocksize = MAXBLOCK; blocksize >= CHUNKSIZE; blocksize >>= 1 ) {
nkeynes@1099
   155
        while( length >= blocksize ) {
nkeynes@1099
   156
            unsigned nchunks = blocksize/CHUNKSIZE;
nkeynes@1099
   157
            for( unsigned i=0; i<nchunks; i++ ) {
nkeynes@1099
   158
                table[i] = i; // Identity
nkeynes@1099
   159
            }
nkeynes@1099
   160
            for( unsigned i = nchunks-1; i != (unsigned)-1; --i ) {
nkeynes@1099
   161
                unsigned j = (NEXT(seed) * i)>>16;
nkeynes@1099
   162
                unsigned tmp = table[i];
nkeynes@1099
   163
                table[i] = table[j];
nkeynes@1099
   164
                table[j] = tmp;
nkeynes@1099
   165
                memcpy( d, s + CHUNKSIZE*table[i], CHUNKSIZE );
nkeynes@1099
   166
                d+= CHUNKSIZE;
nkeynes@1099
   167
            }
nkeynes@1099
   168
            length -= blocksize;
nkeynes@1099
   169
            s += blocksize;
nkeynes@1099
   170
        }
nkeynes@1099
   171
    }
nkeynes@1099
   172
    if( length ) {
nkeynes@1099
   173
        memcpy( d, s, length );
nkeynes@1099
   174
    }
nkeynes@1099
   175
}
nkeynes@1099
   176
nkeynes@1099
   177
void bootprogram_unscramble( unsigned char *dest, unsigned char *src, size_t length )
nkeynes@1099
   178
{
nkeynes@1099
   179
    randseed seed = length & 0xFFFF;
nkeynes@1099
   180
    unsigned table[MAXBLOCK/32];
nkeynes@1099
   181
    unsigned char *s = src;
nkeynes@1099
   182
    unsigned char *d = dest;
nkeynes@1099
   183
nkeynes@1099
   184
    for( unsigned blocksize = MAXBLOCK; blocksize >= CHUNKSIZE; blocksize >>= 1 ) {
nkeynes@1099
   185
        while( length >= blocksize ) {
nkeynes@1099
   186
            unsigned nchunks = blocksize/CHUNKSIZE;
nkeynes@1099
   187
            for( unsigned i=0; i<nchunks; i++ ) {
nkeynes@1099
   188
                table[i] = i; // Identity
nkeynes@1099
   189
            }
nkeynes@1099
   190
            for( unsigned i = nchunks-1; i != (unsigned)-1; --i ) {
nkeynes@1099
   191
                unsigned j = (NEXT(seed) * i)>>16;
nkeynes@1099
   192
                unsigned tmp = table[i];
nkeynes@1099
   193
                table[i] = table[j];
nkeynes@1099
   194
                table[j] = tmp;
nkeynes@1099
   195
                memcpy( d + CHUNKSIZE*table[i], s, CHUNKSIZE );
nkeynes@1099
   196
                s+= CHUNKSIZE;
nkeynes@1099
   197
            }
nkeynes@1099
   198
            length -= blocksize;
nkeynes@1099
   199
            d += blocksize;
nkeynes@1099
   200
        }
nkeynes@1099
   201
    }
nkeynes@1099
   202
    if( length ) {
nkeynes@1099
   203
        memcpy( d, s, length );
nkeynes@1099
   204
    }
nkeynes@1099
   205
}
.