blob: a788375868c0f9acf0cc2979c40abcc8f30fdf9d [file] [log] [blame]
Adithya Baglodya4077392017-05-22 11:27:15 +05301#!/usr/bin/env python3
2
3import os
4import sys
5import struct
6import parser
7from collections import namedtuple
8import ctypes
9import argparse
Adithya Baglodyd1703692017-09-18 16:59:28 +053010import re
11from elftools.elf.elffile import ELFFile
12from elftools.elf.sections import SymbolTableSection
Adithya Baglodya4077392017-05-22 11:27:15 +053013
Adithya Baglodyd1703692017-09-18 16:59:28 +053014# global variables
Adithya Baglodya4077392017-05-22 11:27:15 +053015pd_complete = ''
16inputfile = ''
17outputfile = ''
18list_of_pde = {}
19num_of_regions = 0
Adithya Baglodyd1703692017-09-18 16:59:28 +053020read_buff = ''
21raw_info = []
Adithya Baglodya4077392017-05-22 11:27:15 +053022
Adithya Baglodyd1703692017-09-18 16:59:28 +053023mmu_region_details = namedtuple("mmu_region_details",
24 "pde_index page_entries_info")
Adithya Baglodya4077392017-05-22 11:27:15 +053025
Adithya Baglodyd1703692017-09-18 16:59:28 +053026valid_pages_inside_pde = namedtuple("valid_pages_inside_pde", "start_addr size \
Adithya Baglodya4077392017-05-22 11:27:15 +053027 pte_valid_addr_start \
28 pte_valid_addr_end \
29 permissions")
30
Adithya Baglodyd1703692017-09-18 16:59:28 +053031mmu_region_details_pdpt = namedtuple("mmu_region_details_pdpt",
32 "pdpte_index pd_entries")
33
Adithya Baglodya4077392017-05-22 11:27:15 +053034page_tables_list = []
Adithya Baglodyd1703692017-09-18 16:59:28 +053035pd_tables_list = []
Adithya Baglodya4077392017-05-22 11:27:15 +053036pd_start_addr = 0
37validation_issue_memory_overlap = [False, 0, -1]
38output_offset = 0
39print_string_pde_list = ''
40pde_pte_string = {}
Adithya Baglodyd1703692017-09-18 16:59:28 +053041FourMB = (1024 * 4096) # In Bytes
42
43# Constants
44PAGE_ENTRY_PRESENT = 1
45PAGE_ENTRY_READ_WRITE = 1 << 1
46PAGE_ENTRY_USER_SUPERVISOR = 1 << 2
47PAGE_ENTRY_PWT = 0 << 3
48PAGE_ENTRY_PCD = 0 << 4
49PAGE_ENTRY_ACCESSED = 0 << 5 # this is a read only field
50PAGE_ENTRY_DIRTY = 0 << 6 # this is a read only field
51PAGE_ENTRY_PAT = 0 << 7
52PAGE_ENTRY_GLOBAL = 0 << 8
53PAGE_ENTRY_ALLOC = 1 << 9
54PAGE_ENTRY_CUSTOM = 0 << 10
Adithya Baglodya4077392017-05-22 11:27:15 +053055#############
56
Adithya Baglodyd1703692017-09-18 16:59:28 +053057#*****************************************************************************#
58# class for 4Kb Mode
Adithya Baglodya4077392017-05-22 11:27:15 +053059
60
Adithya Baglodyd1703692017-09-18 16:59:28 +053061class PageMode_4kb:
62 total_pages = 1023
63 write_page_entry_bin = "I"
64 size_addressed_per_pde = (1024 * 4096) # 4MB In Bytes
Adithya Baglodya4077392017-05-22 11:27:15 +053065
Adithya Baglodyd1703692017-09-18 16:59:28 +053066 # return the page directory number for the give address
67 def get_pde_number(self, value):
68 return (value >> 22) & 0x3FF
Adithya Baglodya4077392017-05-22 11:27:15 +053069
Adithya Baglodyd1703692017-09-18 16:59:28 +053070 # return the page table number for the given address
71 def get_pte_number(self, value):
72 return (value >> 12) & 0x3FF
Adithya Baglodya4077392017-05-22 11:27:15 +053073
Adithya Baglodyd1703692017-09-18 16:59:28 +053074 # get the total number of pd available
75 def get_number_of_pd(self):
76 return len(list_of_pde.keys())
Adithya Baglodya4077392017-05-22 11:27:15 +053077
Adithya Baglodyd1703692017-09-18 16:59:28 +053078 # the return value will have the page address and it is assumed
79 # to be a 4096 boundary
80 # hence the output of this API will be a 20bit address of the page table
81 def address_of_page_table(self, page_table_number):
82 global pd_start_addr
83
84 # location from where the Page tables will be written
85 PT_start_addr = pd_start_addr + 4096
86 return ((PT_start_addr +
87 (page_tables_list.index(page_table_number) * 4096) >> 12))
88
89 # union x86_mmu_pde_pt {
90 # u32_t value;
91 # struct {
92 # u32_t p:1;
93 # u32_t rw:1;
94 # u32_t us:1;
95 # u32_t pwt:1;
96 # u32_t pcd:1;
97 # u32_t a:1;
98 # u32_t ignored1:1;
99 # u32_t ps:1;
100 # u32_t ignored2:4;
101 # u32_t page_table:20;
102 # };
103 # };
104 def get_binary_pde_value(self, value):
105 perms = value.page_entries_info[0].permissions
106
107 present = PAGE_ENTRY_PRESENT
108 read_write = check_bits(perms, [1, 29]) << 1
109 user_mode = check_bits(perms, [2, 28]) << 2
110
111 pwt = PAGE_ENTRY_PWT
112 pcd = PAGE_ENTRY_PCD
113 a = PAGE_ENTRY_ACCESSED
114 ps = 0 << 7 # this is a read only field
115 page_table = self.address_of_page_table(value.pde_index) << 12
116 return (present |
117 read_write |
118 user_mode |
119 pwt |
120 pcd |
121 a |
122 ps |
123 page_table)
124
125 # union x86_mmu_pte {
126 # u32_t value;
127 # struct {
128 # u32_t p:1;
129 # u32_t rw:1;
130 # u32_t us:1;
131 # u32_t pwt:1;
132 # u32_t pcd:1;
133 # u32_t a:1;
134 # u32_t d:1;
135 # u32_t pat:1;
136 # u32_t g:1;
137 # u32_t alloc:1;
138 # u32_t custom:2;
139 # u32_t page:20;
140 # };
141 # };
142 def get_binary_pte_value(self, value, pte, perm_for_pte):
143 present = PAGE_ENTRY_PRESENT
144 read_write = ((perm_for_pte >> 1) & 0x1) << 1
145 user_mode = ((perm_for_pte >> 2) & 0x1) << 2
146 pwt = PAGE_ENTRY_PWT
147 pcd = PAGE_ENTRY_PCD
148 a = PAGE_ENTRY_ACCESSED
149 d = PAGE_ENTRY_DIRTY
150 pat = PAGE_ENTRY_PAT
151 g = PAGE_ENTRY_GLOBAL
152 alloc = PAGE_ENTRY_ALLOC
153 custom = PAGE_ENTRY_CUSTOM
154
155 # This points to the actual memory in the HW
156 # totally 20 bits to rep the phy address
157 # first 10 is the number got from pde and next 10 is pte
158 page_table = ((value.pde_index << 10) | pte) << 12
159
160 binary_value = (present | read_write | user_mode |
161 pwt | pcd | a | d | pat | g | alloc | custom |
162 page_table)
163 return binary_value
164
165 def populate_required_structs(self):
166 for region in raw_info:
167 pde_index = self.get_pde_number(region[0])
168 pte_valid_addr_start = self.get_pte_number(region[0])
169
170 # Get the end of the page table entries
171 # Since a memory region can take up only a few entries in the Page
172 # table, this helps us get the last valid PTE.
173 pte_valid_addr_end = self.get_pte_number(region[0] +
174 region[1] - 1)
175
176 mem_size = region[1]
177
178 # In-case the start address aligns with a page table entry other
179 # than zero and the mem_size is greater than (1024*4096) i.e 4MB
180 # in case where it overflows the currenty PDE's range then limit the
181 # PTE to 1024 and so make the mem_size reflect the actual size taken
182 # up in the current PDE
183 if (region[1] + (pte_valid_addr_start * 4096)) >= \
184 (self.size_addressed_per_pde):
185
186 pte_valid_addr_end = self.total_pages
187 mem_size = (((self.total_pages + 1) -
188 pte_valid_addr_start) * 4096)
189
190 self.set_pde_pte_values(pde_index, region[0], mem_size,
191 pte_valid_addr_start,
192 pte_valid_addr_end,
193 region[2])
194
195 if pde_index not in page_tables_list:
196 page_tables_list.append(pde_index)
197
198 # IF the current pde couldn't fit the entire requested region size
199 # then there is a need to create new PDEs to match the size.
200 # Here the overflow_size represents the size that couldn't be fit
201 # inside the current PDE, this is will now to used to create a
202 # new PDE/PDEs so the size remaining will be
203 # requested size - allocated size(in the current PDE)
204
205 overflow_size = region[1] - mem_size
206
207 # create all the extra PDEs needed to fit the requested size
208 # this loop starts from the current pde till the last pde that is
209 # needed the last pde is calcualted as the (start_addr + size) >>
210 # 22
211 if overflow_size != 0:
212 for extra_pde in range(pde_index + 1, self.get_pde_number(
213 region[0] + region[1]) + 1):
214
215 # new pde's start address
216 # each page directory entry has a addr range of (1024 *4096)
217 # thus the new PDE start address is a multiple of that
218 # number
219 extra_pde_start_address = (extra_pde *
Anas Nashif72565532017-12-12 08:19:25 -0500220 (self.size_addressed_per_pde))
Adithya Baglodyd1703692017-09-18 16:59:28 +0530221
222 # the start address of and extra pde will always be 0
223 # and the end address is calculated with the new pde's start
224 # address and the overflow_size
225 extra_pte_valid_addr_end = self.get_pte_number(
226 extra_pde_start_address + overflow_size - 1)
227
228 # if the overflow_size couldn't be fit inside this new pde
229 # then need another pde and so we now need to limit the end
230 # of the PTE to 1024 and set the size of this new region to
231 # the max possible
232 extra_region_size = overflow_size
233 if overflow_size >= (self.size_addressed_per_pde):
234 extra_region_size = self.size_addressed_per_pde
235 extra_pte_valid_addr_end = self.total_pages
236
237 # load the new PDE's details
238
239 self.set_pde_pte_values(extra_pde,
240 extra_pde_start_address,
241 extra_region_size,
242 0,
243 extra_pte_valid_addr_end,
244 region[2])
245
246 # for the next iteration of the loop the size needs to
247 # decreased.
248 overflow_size -= extra_region_size
249
250 # print(hex_32(overflow_size),extra_pde)
251 if extra_pde not in page_tables_list:
252 page_tables_list.append(extra_pde)
253
254 if overflow_size == 0:
255 break
256
257 page_tables_list.sort()
258
259 # update the tuple values for the memory regions needed
260 def set_pde_pte_values(self, pde_index, address, mem_size,
261 pte_valid_addr_start, pte_valid_addr_end, perm):
262
263 pages_tuple = valid_pages_inside_pde(
264 start_addr=address,
265 size=mem_size,
266 pte_valid_addr_start=pte_valid_addr_start,
267 pte_valid_addr_end=pte_valid_addr_end,
268 permissions=perm)
269
270 mem_region_values = mmu_region_details(pde_index=pde_index,
271 page_entries_info=[])
272
273 mem_region_values.page_entries_info.append(pages_tuple)
274
275 if pde_index in list_of_pde.keys():
276 # this step adds the new page info to the exsisting pages info
277 list_of_pde[pde_index].page_entries_info.append(pages_tuple)
278 else:
279 list_of_pde[pde_index] = mem_region_values
280
281 def page_directory_create_binary_file(self):
282 global output_buffer
283 global output_offset
284 for pde in range(self.total_pages + 1):
285 binary_value = 0 # the page directory entry is not valid
286
287 # if i have a valid entry to populate
288 if pde in sorted(list_of_pde.keys()):
289 value = list_of_pde[pde]
290 binary_value = self.get_binary_pde_value(value)
291 self.pde_verbose_output(pde, binary_value)
292
293 struct.pack_into(self.write_page_entry_bin,
294 output_buffer,
295 output_offset,
296 binary_value)
297
298 output_offset += struct.calcsize(self.write_page_entry_bin)
299
300 def page_table_create_binary_file(self):
301 global output_buffer
302 global output_offset
303
304 for key, value in sorted(list_of_pde.items()):
305 for pte in range(self.total_pages + 1):
306 binary_value = 0 # the page directory entry is not valid
307
308 valid_pte = 0
309 for i in value.page_entries_info:
310 temp_value = ((pte >= i.pte_valid_addr_start) and
311 (pte <= i.pte_valid_addr_end))
312 if temp_value:
313 perm_for_pte = i.permissions
314 valid_pte |= temp_value
315
316 # if i have a valid entry to populate
317 if valid_pte:
318 binary_value = self.get_binary_pte_value(value,
319 pte,
320 perm_for_pte)
321 self.pte_verbose_output(key, pte, binary_value)
322
323 struct.pack_into(self.write_page_entry_bin,
324 output_buffer,
325 output_offset,
326 binary_value)
327 output_offset += struct.calcsize(self.write_page_entry_bin)
328
329 # To populate the binary file the module struct needs a buffer of the
330 # excat size. This returns the size needed for the given set of page
331 # tables.
332 def set_binary_file_size(self):
333 binary_size = ctypes.create_string_buffer((4096) +
334 (len(list_of_pde.keys()) *
335 4096))
336 return binary_size
337
338 # prints the details of the pde
339 def verbose_output(self):
340
341 print("\nTotal Page directory entries " + str(self.get_number_of_pd()))
342 count = 0
343 for key, value in list_of_pde.items():
344 for i in value.page_entries_info:
345 count += 1
346 print("In Page directory entry " +
347 format_string(value.pde_index) +
348 ": valid start address = " +
349 hex_32(i.start_addr) + ", end address = " +
350 hex_32((i.pte_valid_addr_end + 1) * 4096 - 1 +
351 (value.pde_index * (FourMB))))
352
353 # print all the tables for a given page table mode
354 def print_all_page_table_info(self):
355 self.pde_print_elements()
356 self.pte_print_elements()
357
358 def pde_verbose_output(self, pde, binary_value):
Andrew Boieb3227fa2017-11-06 10:52:16 -0800359 if args.verbose < 2:
Adithya Baglodyd1703692017-09-18 16:59:28 +0530360 return
361
362 global print_string_pde_list
363
364 present = format_string(binary_value & 0x1)
365 read_write = format_string((binary_value >> 1) & 0x1)
366 user_mode = format_string((binary_value >> 2) & 0x1)
367 pwt = format_string((binary_value >> 3) & 0x1)
368 pcd = format_string((binary_value >> 4) & 0x1)
369 a = format_string((binary_value >> 5) & 0x1)
370 ignored1 = format_string(0)
371 ps = format_string((binary_value >> 7) & 0x1)
372 ignored2 = format_string(0000)
373 page_table_addr = format_string(hex((binary_value >> 12) & 0xFFFFF))
374
375 print_string_pde_list += (format_string(str(pde)) +
376 " | " +
377 (present) +
378 " | " +
379 (read_write) + " | " +
380 (user_mode) + " | " +
381 (pwt) + " | " +
382 (pcd) + " | " +
383 (a) + " | " +
384 (ps) + " | " +
385 page_table_addr + "\n"
386 )
387
388 def pde_print_elements(self):
389 global print_string_pde_list
390 print("PAGE DIRECTORY ")
391 print(format_string("PDE") + " | " +
392 format_string('P') + " | " +
393 format_string('rw') + " | " +
394 format_string('us') + " | " +
395 format_string('pwt') + " | " +
396 format_string('pcd') + " | " +
397 format_string('a') + " | " +
398 format_string('ps') + " | " +
399 format_string('Addr page table'))
400 print(print_string_pde_list)
401 print("END OF PAGE DIRECTORY")
402
403 def pte_verbose_output(self, pde, pte, binary_value):
404 global pde_pte_string
405
406 present = format_string((binary_value >> 0) & 0x1)
407 read_write = format_string((binary_value >> 1) & 0x1)
408 user_mode = format_string((binary_value >> 2) & 0x1)
409 pwt = format_string((binary_value >> 3) & 0x1)
410 pcd = format_string((binary_value >> 4) & 0x1)
411 a = format_string((binary_value >> 5) & 0x1)
412 d = format_string((binary_value >> 6) & 0x1)
413 pat = format_string((binary_value >> 7) & 0x1)
414 g = format_string((binary_value >> 8) & 0x1)
415 alloc = format_string((binary_value >> 9) & 0x1)
416 custom = format_string((binary_value >> 10) & 0x3)
417 page_table_addr = hex_20((binary_value >> 12) & 0xFFFFF)
418
419 print_string_list = (format_string(str(pte)) + " | " +
420 (present) + " | " +
421 (read_write) + " | " +
422 (user_mode) + " | " +
423 (pwt) + " | " +
424 (pcd) + " | " +
425 (a) + " | " +
426 (d) + " | " +
427 (pat) + " | " +
428 (g) + " | " +
429 (alloc) + " | " +
430 (custom) + " | " +
431 page_table_addr + "\n"
432 )
433
434 if pde in pde_pte_string.keys():
435 pde_pte_string[pde] += (print_string_list)
436 else:
437 pde_pte_string[pde] = print_string_list
438
439 def pte_print_elements(self):
440 global pde_pte_string
441
442 for pde, print_string in sorted(pde_pte_string.items()):
443 print("\nPAGE TABLE " + str(pde))
444
445 print(format_string("PTE") + " | " +
446 format_string('P') + " | " +
447 format_string('rw') + " | " +
448 format_string('us') + " | " +
449 format_string('pwt') + " | " +
450 format_string('pcd') + " | " +
451 format_string('a') + " | " +
452 format_string('d') + " | " +
453 format_string('pat') + " | " +
454 format_string('g') + " | " +
455 format_string('alloc') + " | " +
456 format_string('custom') + " | " +
457 format_string('page addr'))
458 print(print_string)
459 print("END OF PAGE TABLE " + str(pde))
460
461
462#*****************************************************************************#
463# class for PAE 4KB Mode
464class PageMode_PAE:
465 total_pages = 511
466 write_page_entry_bin = "Q"
467 size_addressed_per_pde = (512 * 4096) # 2MB In Bytes
468 size_addressed_per_pdpte = (512 * size_addressed_per_pde) # In Bytes
469 list_of_pdpte = {}
470 pdpte_print_string = {}
471 print_string_pdpte_list = ''
472
473 # TODO enable all page tables on just a flag
474
475 def __init__(self):
476 for i in range(4):
477 self.list_of_pdpte[i] = mmu_region_details_pdpt(pdpte_index=i,
478 pd_entries={})
479
480 # return the pdpte number for the give address
481 def get_pdpte_number(self, value):
482 return (value >> 30) & 0x3
483
484 # return the page directory number for the give address
485 def get_pde_number(self, value):
486 return (value >> 21) & 0x1FF
487
488 # return the page table number for the given address
489 def get_pte_number(self, value):
490 return (value >> 12) & 0x1FF
491
492 def get_number_of_pd(self):
493 return len(self.get_pdpte_list())
494
495 def get_pdpte_list(self):
496 return list({temp[0] for temp in pd_tables_list})
497
498 # the return value will have the page address and it is assumed to be a 4096
499 # boundary.hence the output of this API will be a 20bit address of the page
500 # table
501 def address_of_page_table(self, pdpte, page_table_number):
502 global pd_start_addr
503
504 # first page given to page directory pointer
505 # and 2nd page till 5th page are used for storing the page directories.
506
507 # set the max pdpte used. this tells how many pd are needed after
508 # that we start keeping the pt
509 PT_start_addr = self.get_number_of_pd() * 4096 +\
510 pd_start_addr + 4096
511 return (PT_start_addr +
512 (pd_tables_list.index([pdpte, page_table_number]) *
513 4096) >> 12)
514
515 # union x86_mmu_pae_pde {
516 # u64_t value;
517 # struct {
518 # u64_t p:1;
519 # u64_t rw:1;
520 # u64_t us:1;
521 # u64_t pwt:1;
522 # u64_t pcd:1;
523 # u64_t a:1;
524 # u64_t ignored1:1;
525 # u64_t ps:1;
526 # u64_t ignored2:4;
527 # u64_t page_table:20;
528 # u64_t igonred3:29;
529 # u64_t xd:1;
530 # };
531 # };
532
533 def get_binary_pde_value(self, pdpte, value):
534 perms = value.page_entries_info[0].permissions
535
536 present = PAGE_ENTRY_PRESENT
537 read_write = check_bits(perms, [1, 29]) << 1
538 user_mode = check_bits(perms, [2, 28]) << 2
539
540 pwt = PAGE_ENTRY_PWT
541 pcd = PAGE_ENTRY_PCD
542 a = PAGE_ENTRY_ACCESSED
543 ps = 0 << 7 # set to make sure that the phy page is 4KB
544 page_table = self.address_of_page_table(pdpte, value.pde_index) << 12
Jan Kiszka5ae79d02017-11-03 10:58:11 +0100545 xd = 0
Adithya Baglodyd1703692017-09-18 16:59:28 +0530546 return (present |
547 read_write |
548 user_mode |
549 pwt |
550 pcd |
551 a |
552 ps |
553 page_table |
554 xd)
555
556 # union x86_mmu_pae_pte {
557 # u64_t value;
558 # struct {
559 # u64_t p:1;
560 # u64_t rw:1;
561 # u64_t us:1;
562 # u64_t pwt:1;
563 # u64_t pcd:1;
564 # u64_t a:1;
565 # u64_t d:1;
566 # u64_t pat:1;
567 # u64_t g:1;
568 # u64_t ignore:3;
569 # u64_t page:20;
570 # u64_t igonred3:29;
571 # u64_t xd:1;
572 # };
573 # };
574 def get_binary_pte_value(self, value, pde, pte, perm_for_pte):
575 present = PAGE_ENTRY_PRESENT
576 read_write = perm_for_pte & PAGE_ENTRY_READ_WRITE
577 user_mode = perm_for_pte & PAGE_ENTRY_USER_SUPERVISOR
578 pwt = PAGE_ENTRY_PWT
579 pcd = PAGE_ENTRY_PCD
Anas Nashif72565532017-12-12 08:19:25 -0500580 a = PAGE_ENTRY_ALLOC
581 d = PAGE_ENTRY_DIRTY
Adithya Baglodyd1703692017-09-18 16:59:28 +0530582 pat = PAGE_ENTRY_PAT
Anas Nashif72565532017-12-12 08:19:25 -0500583 g = PAGE_ENTRY_GLOBAL
Adithya Baglodyd1703692017-09-18 16:59:28 +0530584
585 # This points to the actual memory in the HW
586 # totally 20 bits to rep the phy address
587 # first 2bits is from pdpte then 9bits is the number got from pde and
588 # next 9bits is pte
589 page_table = ((value.pdpte_index << 18) | (pde << 9) | pte) << 12
590
591 xd = ((perm_for_pte >> 63) & 0x1) << 63
592
593 binary_value = (present | read_write | user_mode |
594 pwt | pcd | a | d | pat | g |
595 page_table | xd)
596 return binary_value
597
598 def clean_up_unused_pdpte(self):
599 self.list_of_pdpte = {key: value for key, value in
600 self.list_of_pdpte.items()
601 if value.pd_entries != {}}
602
603 # update the tuple values for the memory regions needed
604 def set_pde_pte_values(self, pdpte, pde_index, address, mem_size,
605 pte_valid_addr_start, pte_valid_addr_end, perm):
606
607 pages_tuple = valid_pages_inside_pde(
608 start_addr=address,
609 size=mem_size,
610 pte_valid_addr_start=pte_valid_addr_start,
611 pte_valid_addr_end=pte_valid_addr_end,
612 permissions=perm)
613
614 mem_region_values = mmu_region_details(pde_index=pde_index,
615 page_entries_info=[])
616
617 mem_region_values.page_entries_info.append(pages_tuple)
618
619 if pde_index in self.list_of_pdpte[pdpte].pd_entries.keys():
620 # this step adds the new page info to the exsisting pages info
621 self.list_of_pdpte[pdpte].pd_entries[pde_index].\
622 page_entries_info.append(pages_tuple)
623 else:
624 self.list_of_pdpte[pdpte].pd_entries[pde_index] = mem_region_values
625
626 def populate_required_structs(self):
627 for region in raw_info:
628 pdpte_index = self.get_pdpte_number(region[0])
629 pde_index = self.get_pde_number(region[0])
630 pte_valid_addr_start = self.get_pte_number(region[0])
631
632 # Get the end of the page table entries
633 # Since a memory region can take up only a few entries in the Page
634 # table, this helps us get the last valid PTE.
635 pte_valid_addr_end = self.get_pte_number(region[0] +
636 region[1] - 1)
637
638 mem_size = region[1]
639
640 # In-case the start address aligns with a page table entry other
641 # than zero and the mem_size is greater than (1024*4096) i.e 4MB
642 # in case where it overflows the currenty PDE's range then limit the
643 # PTE to 1024 and so make the mem_size reflect the actual size
644 # taken up in the current PDE
645 if (region[1] + (pte_valid_addr_start * 4096)) >= \
646 (self.size_addressed_per_pde):
647
648 pte_valid_addr_end = self.total_pages
649 mem_size = (((self.total_pages + 1) -
650 pte_valid_addr_start) * 4096)
651
652 self.set_pde_pte_values(pdpte_index,
653 pde_index,
654 region[0],
655 mem_size,
656 pte_valid_addr_start,
657 pte_valid_addr_end,
658 region[2])
659
660 if [pdpte_index, pde_index] not in pd_tables_list:
661 pd_tables_list.append([pdpte_index, pde_index])
662
663 # IF the current pde couldn't fit the entire requested region
664 # size then there is a need to create new PDEs to match the size.
665 # Here the overflow_size represents the size that couldn't be fit
666 # inside the current PDE, this is will now to used to create a new
667 # PDE/PDEs so the size remaining will be
668 # requested size - allocated size(in the current PDE)
669
670 overflow_size = region[1] - mem_size
671
672 # create all the extra PDEs needed to fit the requested size
673 # this loop starts from the current pde till the last pde that is
674 # needed the last pde is calcualted as the (start_addr + size) >>
675 # 22
676 if overflow_size != 0:
677 for extra_pdpte in range(pdpte_index,
678 self.get_pdpte_number(region[0] +
679 region[1]) + 1):
680 for extra_pde in range(pde_index + 1, self.get_pde_number(
681 region[0] + region[1]) + 1):
682
683 # new pde's start address
684 # each page directory entry has a addr range of
685 # (1024 *4096) thus the new PDE start address is a
686 # multiple of that number
Anas Nashif72565532017-12-12 08:19:25 -0500687 extra_pde_start_address = (
688 extra_pde * (self.size_addressed_per_pde))
Adithya Baglodyd1703692017-09-18 16:59:28 +0530689
690 # the start address of and extra pde will always be 0
691 # and the end address is calculated with the new
692 # pde's start address and the overflow_size
693 extra_pte_valid_addr_end = (
Anas Nashif72565532017-12-12 08:19:25 -0500694 self.get_pte_number(extra_pde_start_address +
695 overflow_size - 1))
Adithya Baglodyd1703692017-09-18 16:59:28 +0530696
697 # if the overflow_size couldn't be fit inside this new
698 # pde then need another pde and so we now need to limit
699 # the end of the PTE to 1024 and set the size of this
700 # new region to the max possible
701 extra_region_size = overflow_size
702 if overflow_size >= (self.size_addressed_per_pde):
703 extra_region_size = self.size_addressed_per_pde
704 extra_pte_valid_addr_end = self.total_pages
705
706 # load the new PDE's details
707
708 self.set_pde_pte_values(extra_pdpte,
709 extra_pde,
710 extra_pde_start_address,
711 extra_region_size,
712 0,
713 extra_pte_valid_addr_end,
714 region[2])
715
716 # for the next iteration of the loop the size needs
717 # to decreased
718 overflow_size -= extra_region_size
719
720 if [extra_pdpte, extra_pde] not in pd_tables_list:
721 pd_tables_list.append([extra_pdpte, extra_pde])
722
723 if overflow_size == 0:
724 break
725
726 pd_tables_list.sort()
727 self.clean_up_unused_pdpte()
728
729 def pdpte_create_binary_file(self):
730 global output_buffer
731 global output_offset
732 global pd_start_addr
733
734 # pae needs a pdpte at 32byte aligned address
735
736 # Even though we have only 4 entries in the pdpte we need to move
737 # the output_offset variable to the next page to start pushing
738 # the pd contents
739 for pdpte in range(self.total_pages + 1):
740 if pdpte in self.get_pdpte_list():
741 present = 1 << 0
742 pwt = 0 << 3
743 pcd = 0 << 4
744 addr_of_pd = (((pd_start_addr + 4096) +
745 self.get_pdpte_list().index(pdpte) *
746 4096) >> 12) << 12
747 binary_value = (present | pwt | pcd | addr_of_pd)
748 self.pdpte_verbose_output(pdpte, binary_value)
749 else:
750 binary_value = 0
751
752 struct.pack_into(self.write_page_entry_bin,
753 output_buffer,
754 output_offset,
755 binary_value)
756
757 output_offset += struct.calcsize(self.write_page_entry_bin)
758
759 def page_directory_create_binary_file(self):
760 global output_buffer
761 global output_offset
762 pdpte_number_count = 0
763 for pdpte, pde_info in self.list_of_pdpte.items():
764
765 pde_number_count = 0
766 for pde in range(self.total_pages + 1):
767 binary_value = 0 # the page directory entry is not valid
768
769 # if i have a valid entry to populate
770 # if pde in sorted(list_of_pde.keys()):
771 if pde in sorted(pde_info.pd_entries.keys()):
772 value = pde_info.pd_entries[pde]
773 binary_value = self.get_binary_pde_value(pdpte, value)
774 self.pde_verbose_output(pdpte, pde, binary_value)
775
776 pde_number_count += 1
777 struct.pack_into(self.write_page_entry_bin,
778 output_buffer,
779 output_offset,
780 binary_value)
781
782 output_offset += struct.calcsize(self.write_page_entry_bin)
783
784 def page_table_create_binary_file(self):
785 global output_buffer
786 global output_offset
787
788 pdpte_number_count = 0
789 for pdpte, pde_info in sorted(self.list_of_pdpte.items()):
790 pdpte_number_count += 1
791 for pde, pte_info in sorted(pde_info.pd_entries.items()):
792 pte_number_count = 0
793 for pte in range(self.total_pages + 1):
794 binary_value = 0 # the page directory entry is not valid
795
796 valid_pte = 0
797 # go through all the valid pages inside the pde to
798 # figure out if we need to populate this pte
799 for i in pte_info.page_entries_info:
800 temp_value = ((pte >= i.pte_valid_addr_start) and
801 (pte <= i.pte_valid_addr_end))
802 if temp_value:
803 perm_for_pte = i.permissions
804 valid_pte |= temp_value
805
806 # if i have a valid entry to populate
807 if valid_pte:
808 binary_value = self.get_binary_pte_value(pde_info,
809 pde,
810 pte,
811 perm_for_pte)
812 pte_number_count += 1
813 self.pte_verbose_output(pdpte, pde, pte, binary_value)
814
815 # print(binary_value, (self.write_page_entry_bin))
816
817 struct.pack_into(self.write_page_entry_bin,
818 output_buffer,
819 output_offset,
820 binary_value)
821 output_offset += struct.calcsize(self.write_page_entry_bin)
822
Adithya Baglodyd1703692017-09-18 16:59:28 +0530823 # To populate the binary file the module struct needs a buffer of the
824 # excat size This returns the size needed for the given set of page tables.
825 def set_binary_file_size(self):
826 pages_for_pdpte = 1
827 pages_for_pd = self.get_number_of_pd()
828 pages_for_pt = len(pd_tables_list)
829 binary_size = ctypes.create_string_buffer((pages_for_pdpte +
830 pages_for_pd +
831 pages_for_pt) * 4096)
832 return binary_size
833
834 # prints the details of the pde
835 def verbose_output(self):
836 print("\nTotal Page directory Page pointer entries " +
837 str(self.get_number_of_pd()))
838 count = 0
839 for pdpte, pde_info in sorted(self.list_of_pdpte.items()):
840 print(
841 "In page directory page table pointer " +
842 format_string(pdpte))
843
844 for pde, pte_info in sorted(pde_info.pd_entries.items()):
845 for pte in pte_info.page_entries_info:
846 count += 1
847 print(" In Page directory entry " + format_string(pde) +
848 ": valid start address = " +
849 hex_32(pte.start_addr) + ", end address = " +
850 hex_32((pte.pte_valid_addr_end + 1) * 4096 - 1 +
851 (pde * (self.size_addressed_per_pde)) +
852 (pdpte * self.size_addressed_per_pdpte)))
853
854 def pdpte_verbose_output(self, pdpte, binary_value):
Andrew Boieb3227fa2017-11-06 10:52:16 -0800855 if args.verbose < 2:
Adithya Baglodyd1703692017-09-18 16:59:28 +0530856 return
857
858 present = format_string(binary_value & 0x1)
859 pwt = format_string((binary_value >> 3) & 0x1)
860 pcd = format_string((binary_value >> 4) & 0x1)
861 page_table_addr = format_string(hex((binary_value >> 12) & 0xFFFFF))
862
863 self.print_string_pdpte_list += (format_string(str(pdpte)) +
864 " | " + (present) + " | " +
865 (pwt) + " | " +
866 (pcd) + " | " +
867 page_table_addr + "\n")
868
869 def pdpte_print_elements(self):
870 print("\nPAGE DIRECTORIES POINTER ")
871 print(format_string("PDPTE") + " | " +
872 format_string('P') + " | " +
873 format_string('pwt') + " | " +
874 format_string('pcd') + " | " +
875 format_string('Addr'))
876 print(self.print_string_pdpte_list)
877 print("END OF PAGE DIRECTORY POINTER")
878
879 def pde_verbose_output(self, pdpte, pde, binary_value):
Andrew Boieb3227fa2017-11-06 10:52:16 -0800880 if args.verbose < 2:
Adithya Baglodyd1703692017-09-18 16:59:28 +0530881 return
882
883 global print_string_pde_list
884
885 present = format_string(binary_value & 0x1)
886 read_write = format_string((binary_value >> 1) & 0x1)
887 user_mode = format_string((binary_value >> 2) & 0x1)
888 pwt = format_string((binary_value >> 3) & 0x1)
889 pcd = format_string((binary_value >> 4) & 0x1)
890 a = format_string((binary_value >> 5) & 0x1)
891 ignored1 = format_string(0)
892 ps = format_string((binary_value >> 7) & 0x1)
893 ignored2 = format_string(0000)
894 page_table_addr = format_string(hex((binary_value >> 12) & 0xFFFFF))
895 xd = format_string((binary_value >> 63) & 0x1)
896
897 print_string_pde_list = (format_string(str(pde)) + " | " +
898 (present) + " | " +
899 (read_write) + " | " +
900 (user_mode) + " | " +
901 (pwt) + " | " +
902 (pcd) + " | " +
903 (a) + " | " +
904 (ps) + " | " +
905 page_table_addr + " | " +
906 (xd) + "\n")
907
908 if pdpte in self.pdpte_print_string.keys():
909 self.pdpte_print_string[pdpte] += (print_string_pde_list)
910 else:
911 self.pdpte_print_string[pdpte] = print_string_pde_list
912
913 # print all the tables for a given page table mode
914 def print_all_page_table_info(self):
915 self.pdpte_print_elements()
916 self.pde_print_elements()
917 self.pte_print_elements()
918
919 def pde_print_elements(self):
920 global print_string_pde_list
921
922 for pdpte, print_string in sorted(self.pdpte_print_string.items()):
923 print("\n PAGE DIRECTORIES for PDPT " + str(pdpte))
924 print(format_string("PDE") + " | " +
925 format_string('P') + " | " +
926 format_string('rw') + " | " +
927 format_string('us') + " | " +
928 format_string('pwt') + " | " +
929 format_string('pcd') + " | " +
930 format_string('a') + " | " +
931 format_string('ps') + " | " +
932 format_string('Addr') + " | " +
933 format_string('xd'))
934 print(print_string)
935 print("END OF PAGE DIRECTORIES for PDPT " + str(pdpte))
936
937 def pte_verbose_output(self, pdpte, pde, pte, binary_value):
938 global pde_pte_string
939
940 present = format_string((binary_value >> 0) & 0x1)
941 read_write = format_string((binary_value >> 1) & 0x1)
942 user_mode = format_string((binary_value >> 2) & 0x1)
943 pwt = format_string((binary_value >> 3) & 0x1)
944 pcd = format_string((binary_value >> 4) & 0x1)
945 a = format_string((binary_value >> 5) & 0x1)
946 d = format_string((binary_value >> 6) & 0x1)
947 pat = format_string((binary_value >> 7) & 0x1)
948 g = format_string((binary_value >> 8) & 0x1)
949 page_table_addr = hex_20((binary_value >> 12) & 0xFFFFF)
950 xd = format_string((binary_value >> 63) & 0x1)
951
952 print_string_list = (format_string(str(pte)) + " | " +
953 (present) + " | " +
954 (read_write) + " | " +
955 (user_mode) + " | " +
956 (pwt) + " | " +
957 (pcd) + " | " +
958 (a) + " | " +
959 (d) + " | " +
960 (pat) + " | " +
961 (g) + " | " +
962 page_table_addr + " | " +
963 (xd) + "\n"
964 )
965
966 if (pdpte, pde) in pde_pte_string.keys():
967 pde_pte_string[(pdpte, pde)] += (print_string_list)
968 else:
969 pde_pte_string[(pdpte, pde)] = print_string_list
970
971 def pte_print_elements(self):
972 global pde_pte_string
973
974 for (pdpte, pde), print_string in sorted(pde_pte_string.items()):
975 print(
976 "\nPAGE TABLE for PDPTE = " +
977 str(pdpte) +
978 " and PDE = " +
979 str(pde))
980
981 print(format_string("PTE") + " | " +
982 format_string('P') + " | " +
983 format_string('rw') + " | " +
984 format_string('us') + " | " +
985 format_string('pwt') + " | " +
986 format_string('pcd') + " | " +
987 format_string('a') + " | " +
988 format_string('d') + " | " +
989 format_string('pat') + " | " +
990 format_string('g') + " | " +
991 format_string('Page Addr') + " | " +
992 format_string('xd'))
993 print(print_string)
994 print("END OF PAGE TABLE " + str(pde))
995
996
997#*****************************************************************************#
998
Adithya Baglodya4077392017-05-22 11:27:15 +0530999
Adithya Baglodyc5ff7612017-07-11 15:15:37 +05301000def print_list_of_pde(list_of_pde):
1001 for key, value in list_of_pde.items():
Adithya Baglodyd1703692017-09-18 16:59:28 +05301002 print(key, value)
Adithya Baglodyc5ff7612017-07-11 15:15:37 +05301003 print('\n')
Adithya Baglodya4077392017-05-22 11:27:15 +05301004
1005
1006# read the binary from the input file and populate a dict for
1007# start address of mem region
1008# size of the region - so page tables entries will be created with this
1009# read write permissions
Adithya Baglodyd1703692017-09-18 16:59:28 +05301010
1011def read_mmu_list_marshal_param(page_mode):
Adithya Baglodya4077392017-05-22 11:27:15 +05301012
1013 global read_buff
1014 global page_tables_list
1015 global pd_start_addr
1016 global validation_issue_memory_overlap
1017 read_buff = input_file.read()
1018 input_file.close()
Adithya Baglodyc5ff7612017-07-11 15:15:37 +05301019
Adithya Baglodya4077392017-05-22 11:27:15 +05301020 # read contents of the binary file first 2 values read are
1021 # num_of_regions and page directory start address both calculated and
1022 # populated by the linker
Adithya Baglodyd1703692017-09-18 16:59:28 +05301023 num_of_regions, pd_start_addr = struct.unpack_from(
1024 header_values_format, read_buff, 0)
Adithya Baglodya4077392017-05-22 11:27:15 +05301025
1026 # a offset used to remember next location to read in the binary
Adithya Baglodyd1703692017-09-18 16:59:28 +05301027 size_read_from_binary = struct.calcsize(header_values_format)
Adithya Baglodya4077392017-05-22 11:27:15 +05301028
1029 # for each of the regions mentioned in the binary loop and populate all the
1030 # required parameters
1031 for region in range(num_of_regions):
1032 basic_mem_region_values = struct.unpack_from(struct_mmu_regions_format,
Adithya Baglodyd1703692017-09-18 16:59:28 +05301033 read_buff,
1034 size_read_from_binary)
1035 size_read_from_binary += struct.calcsize(struct_mmu_regions_format)
Adithya Baglodya4077392017-05-22 11:27:15 +05301036
Adithya Baglodyd1703692017-09-18 16:59:28 +05301037 # ignore zero sized memory regions
Andrew Boie54ffae72017-08-29 23:20:48 -07001038 if basic_mem_region_values[1] == 0:
1039 continue
1040
Adithya Baglodyd1703692017-09-18 16:59:28 +05301041 # validate for memory overlap here
Adithya Baglodya4077392017-05-22 11:27:15 +05301042 for i in raw_info:
1043 start_location = basic_mem_region_values[0]
Adithya Baglodyd1703692017-09-18 16:59:28 +05301044 end_location = basic_mem_region_values[0] + \
1045 basic_mem_region_values[1]
Adithya Baglodya4077392017-05-22 11:27:15 +05301046
Adithya Baglodyd1703692017-09-18 16:59:28 +05301047 overlap_occurred = ((start_location >= i[0]) and
1048 (start_location <= (i[0] + i[1]))) and \
1049 ((end_location >= i[0]) and
1050 (end_location <= i[0] + i[1]))
Adithya Baglodya4077392017-05-22 11:27:15 +05301051
1052 if overlap_occurred:
Adithya Baglodyd1703692017-09-18 16:59:28 +05301053 validation_issue_memory_overlap = [
1054 True,
1055 start_location,
1056 page_mode.get_pde_number(start_location)]
Adithya Baglodya4077392017-05-22 11:27:15 +05301057 return
1058
1059 # add the retrived info another list
1060 raw_info.append(basic_mem_region_values)
1061
Adithya Baglodya4077392017-05-22 11:27:15 +05301062
1063def validate_pde_regions():
Adithya Baglodyd1703692017-09-18 16:59:28 +05301064 # validation for correct page alignment of the regions
Adithya Baglodya4077392017-05-22 11:27:15 +05301065 for key, value in list_of_pde.items():
1066 for pages_inside_pde in value.page_entries_info:
1067 if pages_inside_pde.start_addr & (0xFFF) != 0:
1068 print("Memory Regions are not page aligned",
1069 hex(pages_inside_pde.start_addr))
1070 sys.exit(2)
1071
Adithya Baglodyd1703692017-09-18 16:59:28 +05301072 # validation for correct page alignment of the regions
Adithya Baglodya4077392017-05-22 11:27:15 +05301073 if pages_inside_pde.size & (0xFFF) != 0:
1074 print("Memory Regions size is not page aligned",
1075 hex(pages_inside_pde.size))
1076 sys.exit(2)
1077
Adithya Baglodyd1703692017-09-18 16:59:28 +05301078 # validation for spiling of the regions across various
Adithya Baglodya4077392017-05-22 11:27:15 +05301079 if validation_issue_memory_overlap[0] == True:
1080 print("Memory Regions are overlapping at memory address " +
Adithya Baglodyd1703692017-09-18 16:59:28 +05301081 str(hex(validation_issue_memory_overlap[1])) +
Adithya Baglodya4077392017-05-22 11:27:15 +05301082 " with Page directory Entry number " +
1083 str(validation_issue_memory_overlap[2]))
1084 sys.exit(2)
1085
1086
Andrew Boie0f16d982017-08-01 16:23:35 -07001087def check_bits(val, bits):
1088 for b in bits:
1089 if val & (1 << b):
1090 return 1
1091 return 0
1092
Adithya Baglodya4077392017-05-22 11:27:15 +05301093
1094# Read the parameters passed to the file
1095def parse_args():
1096 global args
1097
Anas Nashif72565532017-12-12 08:19:25 -05001098 parser = argparse.ArgumentParser(
1099 description=__doc__,
1100 formatter_class=argparse.RawDescriptionHelpFormatter)
Adithya Baglodya4077392017-05-22 11:27:15 +05301101
1102 parser.add_argument("-e", "--big-endian", action="store_true",
1103 help="Target encodes data in big-endian format"
1104 "(little endian is the default)")
1105
1106 parser.add_argument("-i", "--input",
1107 help="Input file from which MMU regions are read.")
Adithya Baglodyd1703692017-09-18 16:59:28 +05301108 parser.add_argument("-k", "--kernel",
1109 help="Zephyr kernel image")
Anas Nashif72565532017-12-12 08:19:25 -05001110 parser.add_argument(
1111 "-o", "--output",
1112 help="Output file into which the page tables are written.")
Andrew Boieb3227fa2017-11-06 10:52:16 -08001113 parser.add_argument("-v", "--verbose", action="count", default=0,
1114 help="Print debugging information. Multiple "
1115 "invocations increase verbosity")
Adithya Baglodya4077392017-05-22 11:27:15 +05301116 args = parser.parse_args()
Sebastian Bøe4971d2a2017-12-28 17:34:50 +01001117 if "VERBOSE" in os.environ:
1118 args.verbose = 1
Adithya Baglodya4077392017-05-22 11:27:15 +05301119
Adithya Baglodyd1703692017-09-18 16:59:28 +05301120
Adithya Baglodya4077392017-05-22 11:27:15 +05301121# the format for writing in the binary file would be decided by the
1122# endian selected
Adithya Baglodyd1703692017-09-18 16:59:28 +05301123def set_struct_endian_format(page_mode):
Adithya Baglodya4077392017-05-22 11:27:15 +05301124 endian_string = "<"
Adithya Baglodyd1703692017-09-18 16:59:28 +05301125 if args.big_endian is True:
Adithya Baglodya4077392017-05-22 11:27:15 +05301126 endian_string = ">"
1127 global struct_mmu_regions_format
1128 global header_values_format
Adithya Baglodya4077392017-05-22 11:27:15 +05301129
Adithya Baglodyd1703692017-09-18 16:59:28 +05301130 struct_mmu_regions_format = endian_string + "IIQ"
Adithya Baglodya4077392017-05-22 11:27:15 +05301131 header_values_format = endian_string + "II"
Adithya Baglodyd1703692017-09-18 16:59:28 +05301132 page_mode.write_page_entry_bin = (endian_string +
1133 page_mode.write_page_entry_bin)
Adithya Baglodya4077392017-05-22 11:27:15 +05301134
1135
1136def format_string(input_str):
1137 output_str = '{0: <5}'.format(str(input_str))
Adithya Baglodyd1703692017-09-18 16:59:28 +05301138 return output_str
Adithya Baglodya4077392017-05-22 11:27:15 +05301139
Adithya Baglodyd1703692017-09-18 16:59:28 +05301140# format for 32bit hex value
Anas Nashif72565532017-12-12 08:19:25 -05001141
1142
Adithya Baglodyc5ff7612017-07-11 15:15:37 +05301143def hex_32(input_value):
Adithya Baglodyd1703692017-09-18 16:59:28 +05301144 output_value = "{0:#0{1}x}".format(input_value, 10)
1145 return output_value
Adithya Baglodyc5ff7612017-07-11 15:15:37 +05301146
Adithya Baglodyd1703692017-09-18 16:59:28 +05301147# format for 20bit hex value
Anas Nashif72565532017-12-12 08:19:25 -05001148
1149
Adithya Baglodyc5ff7612017-07-11 15:15:37 +05301150def hex_20(input_value):
Adithya Baglodyd1703692017-09-18 16:59:28 +05301151 output_value = "{0:#0{1}x}".format(input_value, 7)
1152 return output_value
Adithya Baglodya4077392017-05-22 11:27:15 +05301153
1154
Adithya Baglodyd1703692017-09-18 16:59:28 +05301155def verbose_output(page_mode):
Andrew Boieb3227fa2017-11-06 10:52:16 -08001156 if args.verbose == 0:
Adithya Baglodya4077392017-05-22 11:27:15 +05301157 return
1158
Adithya Baglodyc5ff7612017-07-11 15:15:37 +05301159 print("\nMemory Regions as defined:")
1160 for info in raw_info:
Adithya Baglodyd1703692017-09-18 16:59:28 +05301161 print("Memory region start address = " + hex_32(info[0]) +
1162 ", Memory size = " + hex_32(info[1]) +
1163 ", Permission = " + hex(info[2]))
Adithya Baglodyc5ff7612017-07-11 15:15:37 +05301164
Adithya Baglodyd1703692017-09-18 16:59:28 +05301165 page_mode.verbose_output()
Andrew Boieb3227fa2017-11-06 10:52:16 -08001166
1167 if args.verbose > 1:
1168 page_mode.print_all_page_table_info()
Adithya Baglodyd1703692017-09-18 16:59:28 +05301169
1170# build sym table
Anas Nashif72565532017-12-12 08:19:25 -05001171
1172
Adithya Baglodyd1703692017-09-18 16:59:28 +05301173def get_symbols(obj):
1174 for section in obj.iter_sections():
1175 if isinstance(section, SymbolTableSection):
1176 return {sym.name: sym.entry.st_value
1177 for sym in section.iter_symbols()}
1178
1179 raise LookupError("Could not find symbol table")
Adithya Baglodyc5ff7612017-07-11 15:15:37 +05301180
Adithya Baglodya4077392017-05-22 11:27:15 +05301181
Adithya Baglodyd1703692017-09-18 16:59:28 +05301182# determine which paging mode was selected
1183def get_page_mode():
1184 with open(args.kernel, "rb") as fp:
1185 kernel = ELFFile(fp)
1186 sym = get_symbols(kernel)
1187 try:
1188 return sym["CONFIG_X86_PAE_MODE"]
1189 except BaseException:
1190 return 0
1191
Adithya Baglodya4077392017-05-22 11:27:15 +05301192
1193def main():
1194 global output_buffer
1195 parse_args()
1196
Adithya Baglodyd1703692017-09-18 16:59:28 +05301197 # select the page table needed
1198 if get_page_mode():
1199 page_mode = PageMode_PAE()
1200 else:
1201 page_mode = PageMode_4kb()
1202
1203 set_struct_endian_format(page_mode)
Adithya Baglodya4077392017-05-22 11:27:15 +05301204
1205 global input_file
1206 input_file = open(args.input, 'rb')
1207
1208 global binary_output_file
1209 binary_output_file = open(args.output, 'wb')
1210
1211 # inputfile= file_name
Adithya Baglodyd1703692017-09-18 16:59:28 +05301212 read_mmu_list_marshal_param(page_mode)
Adithya Baglodya4077392017-05-22 11:27:15 +05301213
Adithya Baglodyd1703692017-09-18 16:59:28 +05301214 # populate the required structs
1215 page_mode.populate_required_structs()
1216
1217 # validate the inputs
Adithya Baglodya4077392017-05-22 11:27:15 +05301218 validate_pde_regions()
1219
1220 # The size of the output buffer has to match the number of bytes we write
1221 # this corresponds to the number of page tables gets created.
Adithya Baglodyd1703692017-09-18 16:59:28 +05301222 output_buffer = page_mode.set_binary_file_size()
Adithya Baglodya4077392017-05-22 11:27:15 +05301223
Adithya Baglodyd1703692017-09-18 16:59:28 +05301224 try:
1225 page_mode.pdpte_create_binary_file()
1226 except BaseException:
1227 pass
1228 page_mode.page_directory_create_binary_file()
1229 page_mode.page_table_create_binary_file()
Adithya Baglodya4077392017-05-22 11:27:15 +05301230
Adithya Baglodyd1703692017-09-18 16:59:28 +05301231 # write the binary data into the file
1232 binary_output_file.write(output_buffer)
Adithya Baglodya4077392017-05-22 11:27:15 +05301233 binary_output_file.close()
1234
1235 # verbose output needed by the build system
Adithya Baglodyd1703692017-09-18 16:59:28 +05301236 verbose_output(page_mode)
1237
Adithya Baglodya4077392017-05-22 11:27:15 +05301238
1239if __name__ == "__main__":
Adithya Baglodyd1703692017-09-18 16:59:28 +05301240 main()