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