blob: 6ed6e0ec9a7aeb49051d771428067074e1afe050 [file] [log] [blame]
Michael Karcher703c6b92010-01-14 16:23:23 +01001/*
2 * Copyright 2010 Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19#include <stdio.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <string.h>
24#include <inttypes.h>
25#include <sys/stat.h>
26#include <sys/mman.h>
27
Luc Verhaegen9e43c3a2010-03-27 16:56:06 +010028#if !defined(le32toh) || !defined(le16toh)
29#if BYTE_ORDER == LITTLE_ENDIAN
30#define le32toh(x) (x)
31#define le16toh(x) (x)
32#else
33#include <byteswap.h>
34#define le32toh(x) bswap_32(x)
35#define le16toh(x) bswap_16(x)
36#endif
37#endif
38
Michael Karcher703c6b92010-01-14 16:23:23 +010039struct slabentry {
40 uint32_t destaddr;
41 uint32_t length_flag;
42};
43
44struct slabheader {
45 uint16_t entries;
46 uint16_t headersize;
47 struct slabentry blocks[0];
48};
49
50struct nameentry {
51 uint8_t segtype;
52 uint16_t dtor_offset;
53 char name[0];
54};
55
56int slabextract(const unsigned char *buffer, int bufferlen)
57{
58 const struct slabheader *h = (const void *) buffer;
59 const unsigned char *listpointer;
60 const unsigned char *datapointer;
61 int i, count;
62
63
64 count = le16toh(h->entries);
65 printf("%d entries\n", count);
66
67 /* FIXME: Is the 37 really constant? */
68 if (8 * count + 37 < le32toh(h->headersize)) {
69 listpointer = buffer + 8 * count + 37;
70 printf("Name Tp ");
71 } else {
72 listpointer = NULL; /* No names present */
73 printf("Name ");
74 }
75
76 datapointer = buffer + le32toh(h->headersize);
77
78 printf("LoadAddr size initialized\n");
79
80 for (i = 0; i < count; i++) {
81 const struct slabentry *block;
82 char filename[25];
83 uint32_t len;
84 int has_data;
85
86 if (listpointer) {
87 const struct nameentry *entry = (const void *) listpointer;
88 block = (const void *) (buffer + le16toh(entry->dtor_offset));
89 sprintf(filename, "%.20s.bin", entry->name);
90 listpointer += strlen(entry->name) + 4;
91 printf("%-15s %02x ", entry->name, entry->segtype);
92 } else {
93 block = (const void *) (buffer + 4 + 8 * i);
94 sprintf(filename, "block%02d.bin", i);
95 printf("block%02d ", i);
96 }
97
98 len = le32toh(block->length_flag);
99 if (len & 0x80000000)
100 has_data = 1;
101 else
102 has_data = 0;
103 len &= 0x7fffffff;
104
105 printf("%08x %8d\t %s\n", le32toh(block->destaddr), len,
106 has_data ? "yes" : "no");
107
108 if (has_data) {
109 int outfd = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
110 if (outfd != -1) {
111 if (write(outfd, datapointer, len) != len)
112 fprintf(stderr, "Can't write %s: %s\n", filename,
113 strerror(errno));
114 close(outfd);
115 } else
116 fprintf(stderr, "Can't create output file %s: %s\n", filename,
117 strerror(errno));
118 datapointer += len;
119 }
120 }
121
122 return 0;
123}
124
125int main(int argc, char *argv[])
126{
127 int infd;
128 unsigned char *InputBuffer;
129 int InputBufferSize;
130
131 if (argc != 2) {
132 printf("usage: %s <input file>\n", argv[0]);
133 return 1;
134 }
135
136 infd = open(argv[1], O_RDONLY);
137 if (infd < 0) {
138 fprintf(stderr, "Error: Failed to open %s: %s\n",
139 argv[1], strerror(errno));
140 return 1;
141 }
142
143 InputBufferSize = lseek(infd, 0, SEEK_END);
144 if (InputBufferSize < 0) {
145 fprintf(stderr, "Error: Failed to lseek \"%s\": %s\n",
146 argv[1], strerror(errno));
147 return 1;
148 }
149
150 InputBuffer = mmap(NULL, InputBufferSize, PROT_READ, MAP_PRIVATE, infd, 0);
151 if (InputBuffer < 0) {
152 fprintf(stderr, "Error: Failed to mmap %s: %s\n",
153 argv[1], strerror(errno));
154 return 1;
155 }
156
157 if (InputBufferSize < 0x52) { /* probably incorrect */
158 fprintf(stderr, "Error: \"%s\" is too small to be a SLAB file.\n",
159 argv[1]);
160 return 1;
161 }
162
163 return slabextract(InputBuffer, InputBufferSize);
164}