forked from DooMLoRD/android_bootable_bootloader_lk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mkelf.py
159 lines (137 loc) · 4.44 KB
/
mkelf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env python
#
# DESCRIPTION
#
# Combine one or more files to a elf file.
#
# SYNOPSIS
#
# mkelf.py -o elf file@addr[,ramdisk] ...
#
# elf The path to the output file
# file Input file
# addr ELF vaddr and paddr of this file
# ramdisk Mark this segment to be presented in ATAG list as ramdisk (optional)
# ipl Mark this segment to be handled by the boot code as IPL (optional)
# cmdline Mark this segment to be handled by the boot code as kernel cmdline (optional)
#
import re
import os
import sys
import struct
from optparse import OptionParser
# Elf definitions
PT_NULL = 0
PT_LOAD = 1
PT_NOTE = 4
# SEMC Elf definitions
P_FLAGS_RAMDISK = 0x80000000
P_FLAGS_IPL = 0x40000000 # used for STE U8500
P_FLAGS_CMDLINE = 0x20000000
P_FLAGS_RPM = 0x01000000 # used for QCT MSM8x60
def fatal(message):
print >> sys.stderr, '%s: %s' % (os.path.basename(sys.argv[0]), message)
sys.exit(1)
def parse_inputs(args):
segs = []
for arg in args:
try:
seg = {}
tokens = arg.split('@')
if len(tokens) != 2:
fatal('Incorrect format of input parameter: ' + arg)
seg['file'] = tokens[0]
if tokens[1] == 'cmdline':
seg['addr'] = '0'
seg['flags'] = 'cmdline'
else:
input = re.match("^(0x[0-9a-fA-F]+)(?:,(ramdisk|ipl|entry|rpm))?$", tokens[1]).groups()
seg['addr'] = input[0]
seg['flags'] = input[1]
segs.append(seg)
except AttributeError:
fatal("Incorrect format of input parameter: " + arg)
return segs
def write_elf_header(elf, entry, phnum):
elfhdr = {
'e_ident': '\x7fELF\x01\x01\x01\x61',
'e_type': 2,
'e_machine': 40,
'e_version': 1,
'e_entry': long(entry, 16),
'e_phoff': 52,
'e_shoff': 0,
'e_flags': 0,
'e_ehsize': 52,
'e_phentsize': 32,
'e_phnum': phnum,
'e_shentsize': 0,
'e_shnum': 0,
'e_shstrndx': 0
}
elf.write(struct.pack('<8s8xHHLLLLLHHHHHH',
elfhdr['e_ident'], elfhdr['e_type'], elfhdr['e_machine'],
elfhdr['e_version'], elfhdr['e_entry'], elfhdr['e_phoff'],
elfhdr['e_shoff'], elfhdr['e_flags'], elfhdr['e_ehsize'],
elfhdr['e_phentsize'], elfhdr['e_phnum'], elfhdr['e_shentsize'],
elfhdr['e_shnum'], elfhdr['e_shstrndx']))
def write_elf_phdr(elf, seg):
type = PT_LOAD
flags = 0
if seg['flags'] == 'ramdisk':
flags = P_FLAGS_RAMDISK
elif seg['flags'] == 'ipl':
flags = P_FLAGS_IPL
elif seg['flags'] == 'cmdline':
flags = P_FLAGS_CMDLINE
type = PT_NOTE
elif seg['flags'] == 'rpm':
flags = P_FLAGS_RPM
elfphdr = {
'p_type': type,
'p_offset': seg['offset'],
'p_vaddr': long(seg['addr'], 16),
'p_paddr': long(seg['addr'], 16),
'p_filesz': seg['size'],
'p_memsz': seg['size'],
'p_flags': flags,
'p_align': 0
}
elf.write(struct.pack('<LLLLLLLL',
elfphdr['p_type'],
elfphdr['p_offset'],
elfphdr['p_vaddr'],
elfphdr['p_paddr'],
elfphdr['p_filesz'],
elfphdr['p_memsz'],
elfphdr['p_flags'],
elfphdr['p_align']))
def main(args):
parser = OptionParser("usage: %prog options")
parser.add_option("-o", dest="outputfile", help="path to the output file")
(opts, args) = parser.parse_args()
if not opts.outputfile:
fatal("Missing -o on command line")
if len(args) < 1:
fatal("Missing input files")
offset = 4096
segments = []
for seg in parse_inputs(args):
size = os.path.getsize(seg['file'])
seg['offset'] = offset
seg['size'] = size
segments.append(seg)
offset += size
elf = open(opts.outputfile, 'wb')
write_elf_header(elf, segments[0]['addr'], len(segments))
for seg in segments:
write_elf_phdr(elf, seg)
for seg in segments:
elf.seek(seg['offset'])
f = open(seg['file'], 'rb')
data = f.read()
elf.write(data)
f.close()
elf.close()
if __name__ == "__main__":
main(sys.argv[1:])