1# Copyright (C) 2019-2022 Intel Corporation.
2#
3# SPDX-License-Identifier: BSD-3-Clause
4#
5
6import re
7import sys
8import acrn_config_utilities
9import collections
10
11BOARD_NAME = ''
12BIOS_INFO = ['BIOS Information', 'Vendor:', 'Version:', 'Release Date:', 'BIOS Revision:']
13BASE_BOARD = ['Base Board Information', 'Manufacturer:', 'Product Name:', 'Version:']
14
15LEGACY_TTYS = {
16    'ttyS0':'0x3F8',
17    'ttyS1':'0x2F8',
18    'ttyS2':'0x3E8',
19    'ttyS3':'0x2E8',
20}
21
22VALID_LEGACY_IRQ = []
23ERR_LIST = {}
24USED_RAM_RANGE = {}
25
26HEADER_LICENSE = acrn_config_utilities.open_license() + "\n"
27
28# The data base contains hide pci device
29KNOWN_HIDDEN_PDEVS_BOARD_DB = {
30    'apl-mrb':['00:0d:0'],
31    'apl-up2':['00:0d:0'],
32}
33
34TSN_DEVS = ["8086:4b30", "8086:4b31", "8086:4b32", "8086:4ba0", "8086:4ba1", "8086:4ba2",
35            "8086:4bb0", "8086:4bb1", "8086:4bb2", "8086:a0ac", "8086:43ac", "8086:43a2"]
36GPIO_DEVS = ["8086:4b88", "8086:4b89"]
37TPM_PASSTHRU_BOARD = ['whl-ipc-i5', 'whl-ipc-i7', 'tgl-rvp', 'ehl-crb-b', 'cfl-k700-i7']
38
39KNOWN_CAPS_PCI_DEVS_DB = {
40    "VMSIX":TSN_DEVS + GPIO_DEVS,
41}
42
43P2SB_PASSTHRU_BOARD = ('ehl-crb-b')
44
45def get_info(board_info, msg_s, msg_e):
46    """
47    Get information which specify by argument
48    :param board_info: it is a file what contains information for script to read from
49    :param msg_s: it is a pattern of key stings what start to match from board information
50    :param msg_e: it is a pattern of key stings what end to match from board information
51    """
52    info_start = False
53    info_end = False
54    info_lines = []
55    num = len(msg_s.split())
56
57    with open(board_info, 'rt') as f_board:
58        while True:
59
60            line = f_board.readline()
61            if not line:
62                break
63
64            if " ".join(line.split()[0:num]) == msg_s:
65                info_start = True
66                info_end = False
67                continue
68
69            if " ".join(line.split()[0:num]) == msg_e:
70                info_start = False
71                info_end = True
72                continue
73
74            if info_start and not info_end:
75                info_lines.append(line)
76                continue
77
78            if not info_start and info_end:
79                return info_lines
80
81
82def handle_bios_info(config):
83    """
84    Handle bios information
85    :param config: it is a file pointer of bios information for writing to
86    """
87    bios_lines = get_info(acrn_config_utilities.BOARD_INFO_FILE, "<BIOS_INFO>", "</BIOS_INFO>")
88    board_lines = get_info(acrn_config_utilities.BOARD_INFO_FILE, "<BASE_BOARD_INFO>", "</BASE_BOARD_INFO>")
89    print("/*", file=config)
90
91    if not bios_lines or not board_lines:
92        print(" * DMI info is not found", file=config)
93    else:
94        i_cnt = 0
95        bios_board = BIOS_INFO + BASE_BOARD
96
97        # remove the same value and keep origin sort
98        bios_board_info = list(set(bios_board))
99        bios_board_info.sort(key=bios_board.index)
100
101        bios_board_lines = bios_lines + board_lines
102        bios_info_len = len(bios_lines)
103        for line in bios_board_lines:
104            if i_cnt == bios_info_len:
105                print(" *", file=config)
106
107            i_cnt += 1
108
109            for misc_info in bios_board_info:
110                if misc_info == " ".join(line.split()[0:1]) or misc_info == \
111                        " ".join(line.split()[0:2]) or misc_info == " ".join(line.split()[0:3]):
112                    print(" * {0}".format(line.strip()), file=config)
113
114    print(" */", file=config)
115
116
117def handle_root_dev(line):
118    """Handle if it match root device information pattern
119    :param line: one line of information which had decoded to 'ASCII'
120    """
121    for root_type in line.split():
122        # only support ext4 rootfs
123        if "ext4" in root_type:
124            return True
125
126    return False
127
128
129def get_max_clos_mask(board_file):
130    """
131    Parse CLOS information
132    :param board_file: it is a file what contains board information for script to read from
133    :return: type of rdt resource supported and their corresponding clos max.
134    """
135    rdt_res=[]
136    rdt_res_clos_max=[]
137    rdt_res_mask_max=[]
138
139    clos_lines = get_info(board_file, "<CLOS_INFO>", "</CLOS_INFO>")
140    for line in clos_lines:
141        if line.split(':')[0].strip() == "rdt resources supported":
142            rdt_res = line.split(':')[1].strip()
143        elif line.split(':')[0].strip() == "rdt resource clos max":
144            rdt_res_clos_max = line.split(':')[1].strip()
145        elif line.split(':')[0].strip() == "rdt resource mask max":
146            rdt_res_mask_max = line.split(':')[1].strip()
147
148    if (len(rdt_res) == 0) or (len(rdt_res_clos_max) == 0):
149        return rdt_res, rdt_res_clos_max, rdt_res_mask_max
150    else:
151        return list(re.split(r', |\s |,', rdt_res)), list(map(int, rdt_res_clos_max.split(','))), list(re.split(r', |\s |,', rdt_res_mask_max))
152
153
154def get_rootfs(config_file):
155    """
156    This will get rootfs partition from board information
157    :param config_file: it is a file which contain board information
158    :return: rootfs partition list
159    """
160    root_dev_list = []
161    rootfs_lines = get_info(config_file, "<BLOCK_DEVICE_INFO>", "</BLOCK_DEVICE_INFO>")
162
163    # none 'BLOCK_DEVICE_INFO' tag
164    if rootfs_lines == None:
165        return root_dev_list
166
167    for rootfs_line in rootfs_lines:
168        if not rootfs_line:
169            break
170
171        if not handle_root_dev(rootfs_line):
172            continue
173
174        root_dev = rootfs_line.strip().split(':')[0]
175        root_dev_list.append(root_dev)
176
177    return (root_dev_list, len(root_dev_list))
178
179
180def clos_info_parser(board_info):
181    """ Parse CLOS information """
182    return get_max_clos_mask(board_info)
183
184
185def get_valid_irq(board_info):
186    """
187     This is get available irq from board info file
188     :param board_info:  it is a file what contains board information for script to read from
189     :return: None
190     """
191    global VALID_LEGACY_IRQ
192    val_irq = []
193    irq_info_lines = get_info(board_info, "<AVAILABLE_IRQ_INFO>", "</AVAILABLE_IRQ_INFO>")
194    for irq_string in irq_info_lines:
195        val_irq = [x.strip() for x in irq_string.split(',')]
196
197    VALID_LEGACY_IRQ = val_irq
198
199
200def alloc_irq():
201    """
202      This is allocated an available irq
203      :return: free irq
204      """
205    irq_val = VALID_LEGACY_IRQ.pop(0)
206
207    return irq_val
208
209
210def parser_hv_console():
211    """
212    There may be 3 types in the console item
213    1. BDF:(00:18.2) seri:/dev/ttyS2
214    2. /dev/ttyS2
215    3. ttyS2
216    """
217    ttys_n = ''
218    err_dic = {}
219    ttys = acrn_config_utilities.get_hv_item_tag(acrn_config_utilities.SCENARIO_INFO_FILE, "DEBUG_OPTIONS", "SERIAL_CONSOLE")
220
221    if not ttys or ttys == None:
222        return (err_dic, ttys_n)
223
224    if ttys and 'BDF' in ttys or '/dev' in ttys:
225        ttys_n = ttys.split('/')[2]
226    else:
227        ttys_n = ttys
228
229    return (err_dic, ttys_n)
230
231
232def get_processor_info():
233    """
234    Get cpu processor list
235    :param board_info: it is a file what contains board information
236    :return: cpu processor list
237    """
238    processor_list = []
239    tmp_list = []
240    processor_info = get_info(acrn_config_utilities.BOARD_INFO_FILE, "<CPU_PROCESSOR_INFO>", "</CPU_PROCESSOR_INFO>")
241
242    if not processor_info:
243        key = "CPU PROCESSOR_INFO error:"
244        ERR_LIST[key] = "CPU core is not exists"
245        return processor_list
246
247    for processor_line in processor_info:
248        if not processor_line:
249            break
250
251        processor_list = processor_line.strip().split(',')
252        for processor in processor_list:
253            tmp_list.append(processor.strip())
254        break
255
256    return tmp_list
257
258
259def get_native_ttys_info(board_info):
260    """
261    Get ttySn from board info
262    :param board_info: it is a file what contains board information for script to read from
263    :return: serial port list
264    """
265    ttys_list = []
266    ttys_info = get_info(board_info, "<TTYS_INFO>", "</TTYS_INFO>")
267
268    for ttys_line in ttys_info:
269        if not ttys_line:
270            break
271
272        ttys_dev = ttys_line.split()[0].split(':')[1]
273        ttysn = ttys_dev.split('/')[-1]
274        # currently Service VM OS console can only support legacy serial port
275        if ttysn not in list(LEGACY_TTYS.keys()):
276            continue
277        ttys_list.append(ttys_dev)
278
279    return ttys_list
280
281def get_total_mem():
282    """
283    get total memory size from config file which is dumped from native board
284    :return: integer number of total memory size, Unit: MByte
285    """
286    scale_to_mb = 1
287    total_mem_mb = scale_to_mb
288    mem_lines = get_info(acrn_config_utilities.BOARD_INFO_FILE, "<TOTAL_MEM_INFO>", "</TOTAL_MEM_INFO>")
289    for mem_line in mem_lines:
290        mem_info_list = mem_line.split()
291
292    if len(mem_info_list) <= 1:
293        return total_mem_mb
294
295    if mem_info_list[1] == "kB":
296        scale_to_mb = 1024
297
298    total_mem_mb = int(mem_info_list[0]) / scale_to_mb
299    return total_mem_mb
300
301
302def get_pci_info(board_info):
303    pci_bdf_vpid = {}
304    pci_vid_start = False
305    pci_vid_end = False
306    pci_desc = {}
307    pci_start = False
308    pci_end = False
309
310    with open(board_info, 'r') as f:
311        while True:
312            line = f.readline()
313            if not line:
314                break
315
316            s = " "
317            if s.join(line.split()[0:2]) == "<PCI_DEVICE>":
318                pci_start = True
319                pci_end = False
320                continue
321
322            if s.join(line.split()[0:2]) == "</PCI_DEVICE>":
323                pci_start = False
324                pci_end = True
325                continue
326
327            # all pci device wiht description
328            if pci_start and not pci_end:
329                if "Region" in line and "Memory at" in line:
330                    continue
331                bdf = line.split()[0]
332                pci_desc[bdf] = line
333
334            if s.join(line.split()[0:2]) == "<PCI_VID_PID>":
335                pci_vid_start = True
336                pci_vid_end = False
337                continue
338
339            if s.join(line.split()[0:2]) == "</PCI_VID_PID>":
340                pci_vid_start = False
341                pci_vid_end = True
342                continue
343
344            # all pci device with vid/pid and bdf
345            if pci_vid_start and not pci_vid_end:
346                bdf_str = line.split()[0]
347                vid_pid = line.split()[2]
348                pci_bdf_vpid[bdf_str] = vid_pid
349
350    return (pci_desc, pci_bdf_vpid)
351
352def get_p_state_count():
353    """
354    Get cpu p-state count
355    :return: p-state count
356    """
357    px_info = get_info(acrn_config_utilities.BOARD_INFO_FILE, "<PX_INFO>", "</PX_INFO>")
358    if px_info != None:
359        for line in px_info:
360            if re.search("{.*}", line) == None:
361                px_info.remove(line)
362
363    return len(px_info)
364
365def get_p_state_index_from_ratio(ratio):
366    """
367    Get the closest p-state index that is lesser than or equel to given ratio
368    :return: p-state index; If no px_info found in board file, return 0;
369    """
370    closest_index = 0
371    px_info = get_info(acrn_config_utilities.BOARD_INFO_FILE, "<PX_INFO>", "</PX_INFO>")
372    if px_info != None:
373        for line in px_info:
374            if re.search("{.*}", line) == None:
375                px_info.remove(line)
376
377        i = 0
378        closest_index = 1
379        for line in px_info:
380            l = re.search(r"0x(\w*)UL}", line)
381            if l != None:
382                state_ratio = int(l.group(1), 16) >> 8
383                if state_ratio <= ratio:
384                    closest_index = i
385                    break
386            i += 1
387
388    return closest_index
389
390HI_MMIO_OFFSET = 0
391
392class Bar_Mem:
393    def __init__(self):
394        self.addr = 0
395        self.remapped = False
396
397
398class Bar_Attr:
399    def __init__(self):
400        self.name = 0
401        self.remappable = True
402        self.name_w_i_cnt = 0
403
404class Pci_Dev_Bar_Desc:
405    def __init__(self):
406        self.pci_dev_dic = collections.OrderedDict()
407        self.pci_bar_dic = collections.OrderedDict()
408        self.shm_bar_dic = collections.OrderedDict()
409
410PCI_DEV_BAR_DESC = Pci_Dev_Bar_Desc()
411SUB_NAME_COUNT = collections.OrderedDict()
412
413
414def get_value_after_str(line, key):
415    """ Get the value after cstate string """
416    idx = 0
417    line_in_list = line.split()
418    for idx_key, val in enumerate(line_in_list):
419        if val == key:
420            idx = idx_key
421            break
422
423    return line_in_list[idx + 1]
424
425
426def check_bar_remappable(line):
427    #TODO: check device BAR remappable per ACPI table
428
429    return True
430
431
432def get_size(line):
433
434    # get size string from format, Region n: Memory at x ... [size=NK]
435    size_str = line.split()[-1].strip(']').split('=')[1]
436    if 'G' in size_str:
437        size = int(size_str.strip('G')) * acrn_config_utilities.SIZE_G
438    elif 'M' in size_str:
439        size = int(size_str.strip('M')) * acrn_config_utilities.SIZE_M
440    elif 'K' in size_str:
441        size = int(size_str.strip('K')) * acrn_config_utilities.SIZE_K
442    else:
443        size = int(size_str)
444
445    return size
446
447# round up the running bar_addr to the size of the incoming bar "line"
448def remap_bar_addr_to_high(bar_addr, line):
449    """Generate vbar address"""
450    global HI_MMIO_OFFSET
451    size = get_size(line)
452    cur_addr = acrn_config_utilities.round_up(bar_addr, size)
453    HI_MMIO_OFFSET = cur_addr + size
454    return cur_addr
455
456
457def parser_pci():
458    """ Parse PCI lines """
459    global SUB_NAME_COUNT, HI_MMIO_OFFSET
460    cur_bdf = 0
461    prev_bdf = 0
462    tmp_bar_dic = {}
463    bar_addr = bar_num = '0'
464    cal_sub_pci_name = []
465
466    pci_lines = get_info(acrn_config_utilities.BOARD_INFO_FILE, "<PCI_DEVICE>", "</PCI_DEVICE>")
467
468    for line in pci_lines:
469        tmp_bar_mem = Bar_Mem()
470        # get pci bar information into board_cfg_lib.PCI_DEV_BAR_DESC
471        if "Region" in line and "Memory at" in line:
472            #ignore memory region from SR-IOV capabilities
473            if "size=" not in line:
474                 continue
475
476            try:
477                bar_addr = int(get_value_after_str(line, "at"), 16)
478            except ValueError:
479                continue
480
481            bar_num = line.split()[1].strip(':')
482            if bar_addr >= acrn_config_utilities.SIZE_4G or bar_addr < acrn_config_utilities.SIZE_2G:
483                if not tmp_bar_attr.remappable:
484                    continue
485
486                bar_addr = remap_bar_addr_to_high(HI_MMIO_OFFSET, line)
487                tmp_bar_mem.remapped = True
488
489            tmp_bar_mem.addr = hex(bar_addr)
490            tmp_bar_dic[int(bar_num)] = tmp_bar_mem
491        else:
492            tmp_bar_attr = Bar_Attr()
493            prev_bdf = cur_bdf
494            pci_bdf = line.split()[0]
495            tmp_bar_attr.name = " ".join(line.split(':')[1].split()[1:])
496
497            # remove '[*]' in pci subname
498            if '[' in tmp_bar_attr.name:
499                tmp_bar_attr.name = tmp_bar_attr.name.rsplit('[', 1)[0]
500
501            cal_sub_pci_name.append(tmp_bar_attr.name)
502            tmp_bar_attr.remappable = check_bar_remappable(line)
503            PCI_DEV_BAR_DESC.pci_dev_dic[pci_bdf] = tmp_bar_attr
504            cur_bdf = pci_bdf
505
506            if not prev_bdf:
507                prev_bdf = cur_bdf
508
509            if tmp_bar_dic and cur_bdf != prev_bdf:
510                PCI_DEV_BAR_DESC.pci_bar_dic[prev_bdf] = tmp_bar_dic
511
512            # clear the tmp_bar_dic before store the next dic
513            tmp_bar_dic = {}
514
515    # output all the pci device list to pci_device.h
516    for item in cal_sub_pci_name:
517        SUB_NAME_COUNT[item] = SUB_NAME_COUNT.get(item, 0) + 1
518
519    if tmp_bar_dic:
520        PCI_DEV_BAR_DESC.pci_bar_dic[cur_bdf] = tmp_bar_dic
521
522
523def parse_mem():
524    raw_shmem_regions = acrn_config_utilities.get_hv_item_tag(acrn_config_utilities.SCENARIO_INFO_FILE, "FEATURES", "IVSHMEM", "IVSHMEM_REGION")
525
526    global USED_RAM_RANGE
527    for shm_name, shm_bar_dic in PCI_DEV_BAR_DESC.shm_bar_dic.items():
528        if 0 in shm_bar_dic.keys() and int(shm_bar_dic[0].addr, 16) in USED_RAM_RANGE.keys():
529            del USED_RAM_RANGE[int(shm_bar_dic[0].addr, 16)]
530        if 2 in shm_bar_dic.keys() and int(shm_bar_dic[2].addr, 16)-0xC in USED_RAM_RANGE.keys():
531            del USED_RAM_RANGE[int(shm_bar_dic[2].addr, 16)-0xC]
532
533    idx = 0
534    for shm in raw_shmem_regions:
535        if shm is None or shm.strip() == '':
536            continue
537        shm_splited = shm.split(',')
538        name = shm_splited[0].strip()
539        size = shm_splited[1].strip()
540
541        try:
542            int_size = int(size) * 0x100000
543        except:
544            int_size = 0
545        ram_range = get_ram_range()
546        tmp_bar_dict  = {}
547        hv_start_offset = 0x80000000
548        ret_start_addr = find_avl_memory(ram_range, str(0x200100), hv_start_offset)
549        bar_mem_0 = Bar_Mem()
550        bar_mem_0.addr = hex(acrn_config_utilities.round_up(int(ret_start_addr, 16), 0x200000))
551        USED_RAM_RANGE[int(bar_mem_0.addr, 16)] = 0x100
552        tmp_bar_dict[0] = bar_mem_0
553        ram_range = get_ram_range()
554        hv_start_offset2 = 0x100000000
555        ret_start_addr2 = find_avl_memory(ram_range, str(int_size + 0x200000), hv_start_offset2)
556        bar_mem_2 = Bar_Mem()
557        bar_mem_2.addr = hex(acrn_config_utilities.round_up(int(ret_start_addr2, 16), 0x200000) + 0xC)
558        USED_RAM_RANGE[acrn_config_utilities.round_up(int(ret_start_addr2, 16), 0x20000)] = int_size
559        tmp_bar_dict[2] = bar_mem_2
560        PCI_DEV_BAR_DESC.shm_bar_dic[str(idx)+'_'+name] = tmp_bar_dict
561        idx += 1
562
563
564def is_rdt_supported():
565    """
566    Returns True if platform supports RDT else False
567    """
568    (rdt_resources, rdt_res_clos_max, _) = clos_info_parser(acrn_config_utilities.BOARD_INFO_FILE)
569    if len(rdt_resources) == 0 or len(rdt_res_clos_max) == 0:
570        return False
571    else:
572        return True
573
574
575def is_rdt_enabled():
576    """
577    Returns True if RDT enabled else False
578    """
579    rdt_enabled = acrn_config_utilities.get_hv_item_tag(acrn_config_utilities.SCENARIO_INFO_FILE, "FEATURES", "RDT", "RDT_ENABLED")
580    if is_rdt_supported() and rdt_enabled == 'y':
581        return True
582    return False
583
584
585def is_cdp_enabled():
586    """
587    Returns True if platform supports RDT/CDP else False
588    """
589    rdt_enabled = is_rdt_enabled()
590    cdp_enabled = acrn_config_utilities.get_hv_item_tag(acrn_config_utilities.SCENARIO_INFO_FILE, "FEATURES", "RDT", "CDP_ENABLED")
591    if rdt_enabled and cdp_enabled == 'y':
592        return True
593
594    return False
595
596
597def get_rdt_select_opt():
598
599    support_sel = ['n']
600    if is_rdt_supported():
601        support_sel.append('y')
602    return support_sel
603
604
605def get_common_clos_max():
606
607    common_clos_max = 0
608    (res_info, rdt_res_clos_max, clos_max_mask_list) = clos_info_parser(acrn_config_utilities.BOARD_INFO_FILE)
609    if is_rdt_enabled() and not is_cdp_enabled():
610        common_clos_max = min(rdt_res_clos_max)
611
612    if is_cdp_enabled():
613        tmp_clos_max_list = []
614        for res, clos_max in zip(res_info, rdt_res_clos_max):
615            if res == 'MBA':
616                tmp_clos_max_list.append(clos_max)
617            else:
618                tmp_clos_max_list.append(clos_max//2)
619        common_clos_max = min(tmp_clos_max_list)
620
621    return common_clos_max
622
623
624def get_sub_pci_name(i_cnt, bar_attr):
625    tmp_sub_name = ''
626    # if there is only one host bridge, then will discard the index of suffix
627    if i_cnt == 0 and bar_attr.name.upper() == "HOST BRIDGE":
628        tmp_sub_name = "_".join(bar_attr.name.split()).upper()
629    else:
630        if '-' in bar_attr.name:
631            tmp_sub_name = acrn_config_utilities.undline_name(bar_attr.name) + "_" + str(i_cnt)
632        else:
633            tmp_sub_name = "_".join(bar_attr.name.split()).upper() + "_" + str(i_cnt)
634
635    return tmp_sub_name
636
637def get_known_caps_pci_devs():
638    known_caps_pci_devs = {}
639    vpid_lines = get_info(acrn_config_utilities.BOARD_INFO_FILE, "<PCI_VID_PID>", "</PCI_VID_PID>")
640    for dev,known_dev in KNOWN_CAPS_PCI_DEVS_DB.items():
641        if dev not in known_caps_pci_devs:
642            known_caps_pci_devs[dev] = []
643        for k_dev in known_dev:
644            for vpid_line in vpid_lines:
645                if k_dev in vpid_line:
646                    bdf = vpid_line.split()[0]
647                    known_caps_pci_devs[dev].append(bdf)
648                    break
649
650    return known_caps_pci_devs
651
652
653def is_tpm_passthru():
654
655    tpm_passthru = False
656    (_, board) = acrn_config_utilities.get_board_name()
657    tpm2_passthru_enabled = acrn_config_utilities.get_leaf_tag_map(acrn_config_utilities.SCENARIO_INFO_FILE, "mmio_resources", "TPM2")
658    if board in TPM_PASSTHRU_BOARD and tpm2_passthru_enabled and 'y' in tpm2_passthru_enabled.values():
659        tpm_passthru = True
660
661    return tpm_passthru
662
663
664def find_avl_memory(ram_range, hpa_size, hv_start_offset):
665    """
666    This is get hv address from System RAM as host physical size
667    :param ram_range: System RAM mapping
668    :param hpa_size: fixed host physical size
669    :param hv_start_offset: base address of HV RAM start
670    :return: start host physical address
671    """
672    ret_start_addr = 0
673    tmp_order_key = 0
674    int_hpa_size = int(hpa_size, 10)
675
676    tmp_order_key = sorted(ram_range)
677    for start_addr in tmp_order_key:
678        mem_range = ram_range[start_addr]
679        if start_addr <= hv_start_offset and hv_start_offset + int_hpa_size <= start_addr + mem_range:
680            ret_start_addr = hv_start_offset
681            break
682        elif start_addr >= hv_start_offset and mem_range >= int_hpa_size:
683            ret_start_addr = start_addr
684            break
685
686    return hex(ret_start_addr)
687
688
689def get_ram_range():
690    """ Get System RAM range mapping """
691    # read system ram from board_info.xml
692    ram_range = {}
693
694    io_mem_lines = get_info(
695        acrn_config_utilities.BOARD_INFO_FILE, "<IOMEM_INFO>", "</IOMEM_INFO>")
696
697    for line in io_mem_lines:
698        if 'System RAM' not in line:
699            continue
700        start_addr = int(line.split('-')[0], 16)
701        end_addr = int(line.split('-')[1].split(':')[0], 16)
702        mem_range = end_addr - start_addr
703        ram_range[start_addr] = mem_range
704
705    global USED_RAM_RANGE
706    tmp_order_key_used = sorted(USED_RAM_RANGE)
707    for start_addr_used in tmp_order_key_used:
708        mem_range_used = USED_RAM_RANGE[start_addr_used]
709        tmp_order_key = sorted(ram_range)
710        for start_addr in tmp_order_key:
711            mem_range = ram_range[start_addr]
712            if start_addr < start_addr_used and start_addr_used + mem_range_used < start_addr + mem_range:
713                ram_range[start_addr] = start_addr_used - start_addr
714                ram_range[start_addr_used+mem_range_used] = start_addr + mem_range - start_addr_used - mem_range_used
715                break
716            elif start_addr == start_addr_used and start_addr_used + mem_range_used < start_addr + mem_range:
717                del ram_range[start_addr]
718                ram_range[start_addr_used + mem_range_used] = start_addr + mem_range - start_addr_used - mem_range_used
719                break
720            elif start_addr < start_addr_used and start_addr_used + mem_range_used == start_addr + mem_range:
721                ram_range[start_addr] = start_addr_used - start_addr
722                break
723            elif start_addr == start_addr_used and start_addr_used + mem_range_used == start_addr + mem_range:
724                del ram_range[start_addr]
725                break
726            else:
727                continue
728
729    return ram_range
730
731
732def is_p2sb_passthru_possible():
733
734    p2sb_passthru = False
735    (_, board) = acrn_config_utilities.get_board_name()
736    if board in P2SB_PASSTHRU_BOARD:
737        p2sb_passthru = True
738
739    return p2sb_passthru
740
741
742def is_matched_board(boardlist):
743
744    (_, board) = acrn_config_utilities.get_board_name()
745
746    return board in boardlist
747
748
749def find_p2sb_bar_addr():
750    if not is_matched_board(('ehl-crb-b')):
751        acrn_config_utilities.print_red('find_p2sb_bar_addr() can only be called for board ehl-crb-b', err=True)
752        sys.exit(1)
753
754    iomem_lines = get_info(acrn_config_utilities.BOARD_INFO_FILE, "<IOMEM_INFO>", "</IOMEM_INFO>")
755
756    for line in iomem_lines:
757        if 'INTC1020:' in line:
758            start_addr = int(line.split('-')[0], 16) & 0xFF000000
759            return start_addr
760
761    acrn_config_utilities.print_red('p2sb device is not found in board file %s!\n' % acrn_config_utilities.BOARD_INFO_FILE, err=True)
762    sys.exit(1)
763