Subversion Repositories freemyipod

Rev

Rev 655 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
469 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "emcorelib.h"
25
#include "export/libboot.h"
26
 
27
 
655 theseven 28
static struct libboot_api apitable =
469 theseven 29
{
658 theseven 30
    .verify_rockbox_checksum = verify_rockbox_checksum,
31
    .check_firmware = check_firmware,
32
    .load_from_file = load_from_file,
33
    .load_from_flash = load_from_flash
469 theseven 34
};
35
 
36
 
651 theseven 37
EMCORE_LIB_HEADER(LIBBOOT_IDENTIFIER, LIBBOOT_API_VERSION, LIBBOOT_MIN_API_VERSION,
38
                  NULL, NULL, apitable)
469 theseven 39
 
40
 
41
int verify_rockbox_checksum(void* image, size_t size)
42
{
43
    int i;
44
    uint8_t* data = (uint8_t*)image;
45
    uint32_t checksum = data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
46
    uint32_t platform;
47
    switch (get_platform_id())
48
    {
49
        case 0x47324e49:  // IN2G
50
            checksum -= 62;
51
            platform = 0x67326e6e;  // nn2g
52
            break;
53
        case 0x4c435049:  // IPCL
54
            checksum -= 71;
55
            platform = 0x67367069;  // ip6g
56
            break;
57
        default:
58
            return -3;
59
    }
60
    if (*((uint32_t*)&data[4]) != platform) return -2;
61
    for (i = 0; i < size - 8; i++)
62
    {
63
        data[i] = data[i + 8];
64
        checksum -= data[i + 8];
65
    }
66
    if (checksum) return -1;
67
    return 0;
68
}
658 theseven 69
 
70
void check_firmware(void** firmware, int* size, bool verify,
71
                    void* buf, int maxsize, bool compressed)
72
{
73
    if (compressed && maxsize)
74
    {
75
        void* buf2 = malloc(maxsize);
76
        if (buf2)
77
        {
78
            if (!ucl_decompress(buf, *size, buf2, (uint32_t*)size))
79
            {
80
                free(buf);
81
                buf = realloc(buf2, *size);
82
                if (!buf) buf = buf2;
83
                if (!verify || !verify_rockbox_checksum(buf, *size))
84
                    *firmware = buf;
85
                else free(buf);
86
            }
87
            else
88
            {
89
                free(buf2);
90
                free(buf);
91
            }
92
        }
93
        else free(buf);
94
    }
95
    else if (!compressed)
96
    {
97
        if (!verify || !verify_rockbox_checksum(buf, *size)) *firmware = buf;
98
        else free(buf);
99
    }
100
}
101
 
102
void load_from_file(void** firmware, int* size, bool verify, const char* filename, int maxsize)
103
{
104
    int fd = file_open(filename, O_RDONLY);
105
    if (fd > 0)
106
    {
107
        *size = filesize(fd);
108
        if (*size > 0)
109
        {
110
            void* buf = memalign(0x10, *size);
111
            if (buf)
112
            {
113
                if (read(fd, buf, *size) == *size)
114
                    check_firmware(firmware, size, verify, buf, maxsize, maxsize);
115
                else free(buf);
116
            }
117
        }
118
        close(fd);
119
    }
120
}
121
 
122
void load_from_flash(void** firmware, int* size, bool verify, const char* filename, int maxsize)
123
{
124
    *size = bootflash_filesize(filename);
125
    if (*size > 0)
126
    {
127
        void* buf = memalign(0x10, *size);
128
        if (buf)
129
        {
130
            bootflash_read(filename, buf, 0, *size);
131
            check_firmware(firmware, size, verify, buf, maxsize,
132
                           bootflash_attributes(filename) & 0x800);
133
        }
134
    }
135
}