summaryrefslogtreecommitdiff
path: root/firmware/common/rb-loader.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common/rb-loader.c')
-rw-r--r--firmware/common/rb-loader.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/firmware/common/rb-loader.c b/firmware/common/rb-loader.c
new file mode 100644
index 0000000000..10807f9c96
--- /dev/null
+++ b/firmware/common/rb-loader.c
@@ -0,0 +1,115 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2005 by Linus Nielsen Feltzing
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 1
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#include <stdio.h>
22#include "config.h"
23#include "system.h"
24#include "file.h"
25#include "rb-loader.h"
26#include "loader_strerror.h"
27
28/* Load firmware image in a format created by add method of tools/scramble
29 * on success we return size loaded image
30 * on error we return negative value which can be deciphered by means
31 * of strerror() function
32 */
33int load_firmware(unsigned char* buf, const char* firmware, int buffer_size)
34{
35 char filename[MAX_PATH];
36 int fd;
37 int rc;
38 int len;
39 int ret = 0;
40 unsigned long chksum;
41 unsigned long sum;
42 int i;
43
44 /* only filename passed */
45 if (firmware[0] != '/')
46 {
47 /* First check in BOOTDIR */
48 snprintf(filename, sizeof(filename), BOOTDIR "/%s",firmware);
49
50 fd = open(filename, O_RDONLY);
51 if(fd < 0)
52 {
53 /* Check in root dir */
54 snprintf(filename, sizeof(filename),"/%s",firmware);
55 fd = open(filename, O_RDONLY);
56
57 if (fd < 0)
58 return EFILE_NOT_FOUND;
59 }
60 }
61 else
62 {
63 /* full path passed */
64 fd = open(firmware, O_RDONLY);
65 if (fd < 0)
66 return EFILE_NOT_FOUND;
67 }
68
69 len = filesize(fd) - 8;
70
71 if (len > buffer_size)
72 {
73 ret = EFILE_TOO_BIG;
74 goto end;
75 }
76
77 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
78
79 rc = read(fd, &chksum, 4);
80 chksum = betoh32(chksum); /* Rockbox checksums are big-endian */
81 if(rc < 4)
82 {
83 ret = EREAD_CHKSUM_FAILED;
84 goto end;
85 }
86
87 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
88
89 rc = read(fd, buf, len);
90 if(rc < len)
91 {
92 ret = EREAD_IMAGE_FAILED;
93 goto end;
94 }
95
96 sum = MODEL_NUMBER;
97
98 for(i = 0;i < len;i++)
99 {
100 sum += buf[i];
101 }
102
103 if(sum != chksum)
104 {
105 ret = EBAD_CHKSUM;
106 goto end;
107 }
108
109 ret = len;
110
111end:
112 close(fd);
113 return ret;
114}
115