Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
powerpc
boot
addnote.c
Go to the documentation of this file.
1
/*
2
* Program to hack in a PT_NOTE program header entry in an ELF file.
3
* This is needed for OF on RS/6000s to load an image correctly.
4
* Note that OF needs a program header entry for the note, not an
5
* ELF section.
6
*
7
* Copyright 2000 Paul Mackerras.
8
*
9
* This program is free software; you can redistribute it and/or
10
* modify it under the terms of the GNU General Public License
11
* as published by the Free Software Foundation; either version
12
* 2 of the License, or (at your option) any later version.
13
*
14
* Usage: addnote zImage
15
*/
16
#include <
stdio.h
>
17
#include <
stdlib.h
>
18
#include <fcntl.h>
19
#include <unistd.h>
20
#include <
string.h
>
21
22
/* CHRP note section */
23
static
const
char
arch
[] =
"PowerPC"
;
24
25
#define N_DESCR 6
26
unsigned
int
descr
[
N_DESCR
] = {
27
0xffffffff,
/* real-mode = true */
28
0x02000000,
/* real-base, i.e. where we expect OF to be */
29
0xffffffff,
/* real-size */
30
0xffffffff,
/* virt-base */
31
0xffffffff,
/* virt-size */
32
0x4000,
/* load-base */
33
};
34
35
/* RPA note section */
36
static
const
char
rpaname[] =
"IBM,RPA-Client-Config"
;
37
38
/*
39
* Note: setting ignore_my_client_config *should* mean that OF ignores
40
* all the other fields, but there is a firmware bug which means that
41
* it looks at the splpar field at least. So these values need to be
42
* reasonable.
43
*/
44
#define N_RPA_DESCR 8
45
unsigned
int
rpanote
[
N_RPA_DESCR
] = {
46
0,
/* lparaffinity */
47
64,
/* min_rmo_size */
48
0,
/* min_rmo_percent */
49
40,
/* max_pft_size */
50
1,
/* splpar */
51
-1,
/* min_load */
52
0,
/* new_mem_def */
53
1,
/* ignore_my_client_config */
54
};
55
56
#define ROUNDUP(len) (((len) + 3) & ~3)
57
58
unsigned
char
buf
[512];
59
60
#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1]))
61
#define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2))
62
63
#define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \
64
buf[(off) + 1] = (v) & 0xff)
65
#define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \
66
PUT_16BE((off) + 2, (v)))
67
68
/* Structure of an ELF file */
69
#define E_IDENT 0
/* ELF header */
70
#define E_PHOFF 28
71
#define E_PHENTSIZE 42
72
#define E_PHNUM 44
73
#define E_HSIZE 52
/* size of ELF header */
74
75
#define EI_MAGIC 0
/* offsets in E_IDENT area */
76
#define EI_CLASS 4
77
#define EI_DATA 5
78
79
#define PH_TYPE 0
/* ELF program header */
80
#define PH_OFFSET 4
81
#define PH_FILESZ 16
82
#define PH_HSIZE 32
/* size of program header */
83
84
#define PT_NOTE 4
/* Program header type = note */
85
86
#define ELFCLASS32 1
87
#define ELFDATA2MSB 2
88
89
unsigned
char
elf_magic
[4] = { 0x7f,
'E'
,
'L'
,
'F'
};
90
91
int
92
main
(
int
ac
,
char
**
av
)
93
{
94
int
fd
,
n
,
i
;
95
int
ph
,
ps
, np;
96
int
nnote, nnote2,
ns
;
97
98
if
(ac != 2) {
99
fprintf
(stderr,
"Usage: %s elf-file\n"
, av[0]);
100
exit
(1);
101
}
102
fd =
open
(av[1],
O_RDWR
);
103
if
(fd < 0) {
104
perror(av[1]);
105
exit
(1);
106
}
107
108
nnote = 12 +
ROUNDUP
(
strlen
(
arch
) + 1) +
sizeof
(
descr
);
109
nnote2 = 12 +
ROUNDUP
(
strlen
(rpaname) + 1) +
sizeof
(
rpanote
);
110
111
n =
read
(fd,
buf
,
sizeof
(
buf
));
112
if
(n < 0) {
113
perror(
"read"
);
114
exit
(1);
115
}
116
117
if
(n <
E_HSIZE
||
memcmp
(&
buf
[
E_IDENT
+
EI_MAGIC
],
elf_magic
, 4) != 0)
118
goto
notelf;
119
120
if
(
buf
[
E_IDENT
+
EI_CLASS
] !=
ELFCLASS32
121
||
buf
[
E_IDENT
+
EI_DATA
] !=
ELFDATA2MSB
) {
122
fprintf
(stderr,
"%s is not a big-endian 32-bit ELF image\n"
,
123
av[1]);
124
exit
(1);
125
}
126
127
ph =
GET_32BE
(
E_PHOFF
);
128
ps =
GET_16BE
(
E_PHENTSIZE
);
129
np =
GET_16BE
(
E_PHNUM
);
130
if
(ph <
E_HSIZE
|| ps <
PH_HSIZE
|| np < 1)
131
goto
notelf;
132
if
(ph + (np + 2) * ps + nnote + nnote2 > n)
133
goto
nospace;
134
135
for
(i = 0; i < np; ++
i
) {
136
if
(
GET_32BE
(ph +
PH_TYPE
) ==
PT_NOTE
) {
137
fprintf
(stderr,
"%s already has a note entry\n"
,
138
av[1]);
139
exit
(0);
140
}
141
ph +=
ps
;
142
}
143
144
/* XXX check that the area we want to use is all zeroes */
145
for
(i = 0; i < 2 * ps + nnote + nnote2; ++
i
)
146
if
(
buf
[ph + i] != 0)
147
goto
nospace;
148
149
/* fill in the program header entry */
150
ns = ph + 2 *
ps
;
151
PUT_32BE
(ph +
PH_TYPE
,
PT_NOTE
);
152
PUT_32BE
(ph +
PH_OFFSET
, ns);
153
PUT_32BE
(ph +
PH_FILESZ
, nnote);
154
155
/* fill in the note area we point to */
156
/* XXX we should probably make this a proper section */
157
PUT_32BE
(ns,
strlen
(
arch
) + 1);
158
PUT_32BE
(ns + 4,
N_DESCR
* 4);
159
PUT_32BE
(ns + 8, 0x1275);
160
strcpy
((
char
*) &
buf
[ns + 12],
arch
);
161
ns += 12 +
strlen
(
arch
) + 1;
162
for
(i = 0; i <
N_DESCR
; ++
i
, ns += 4)
163
PUT_32BE
(ns,
descr
[i]);
164
165
/* fill in the second program header entry and the RPA note area */
166
ph +=
ps
;
167
PUT_32BE
(ph +
PH_TYPE
,
PT_NOTE
);
168
PUT_32BE
(ph +
PH_OFFSET
, ns);
169
PUT_32BE
(ph +
PH_FILESZ
, nnote2);
170
171
/* fill in the note area we point to */
172
PUT_32BE
(ns,
strlen
(rpaname) + 1);
173
PUT_32BE
(ns + 4,
sizeof
(
rpanote
));
174
PUT_32BE
(ns + 8, 0x12759999);
175
strcpy
((
char
*) &
buf
[ns + 12], rpaname);
176
ns += 12 +
ROUNDUP
(
strlen
(rpaname) + 1);
177
for
(i = 0; i <
N_RPA_DESCR
; ++
i
, ns += 4)
178
PUT_32BE
(ns,
rpanote
[i]);
179
180
/* Update the number of program headers */
181
PUT_16BE
(
E_PHNUM
, np + 2);
182
183
/* write back */
184
lseek(fd, (
long
) 0,
SEEK_SET
);
185
i =
write
(fd,
buf
, n);
186
if
(i < 0) {
187
perror(
"write"
);
188
exit
(1);
189
}
190
if
(i < n) {
191
fprintf
(stderr,
"%s: write truncated\n"
, av[1]);
192
exit
(1);
193
}
194
195
exit
(0);
196
197
notelf:
198
fprintf
(stderr,
"%s does not appear to be an ELF file\n"
, av[1]);
199
exit
(1);
200
201
nospace:
202
fprintf
(stderr,
"sorry, I can't find space in %s to put the note\n"
,
203
av[1]);
204
exit
(1);
205
}
Generated on Thu Jan 10 2013 13:13:06 for Linux Kernel by
1.8.2