1#!/usr/bin/env python3
2#
3# Copyright (C) 2022 Intel Corporation.
4#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7
8import sys
9import acrn_config_utilities, lib.error
10from acrn_config_utilities import get_node
11from collections import defaultdict
12
13# The COM1 was used for console vUART, so we alloc io_port frome COM2~COM4
14val = lambda:list(range(0x9000, 0x9100, 8))
15vm_port_list = defaultdict(val)
16
17def create_s5_vuart_connection(allocation_etree, service_vm_name, service_vm_port, user_vm_name, user_vm_port):
18    vuart_connections_node = get_node(f"/acrn-config/hv/vuart_connections", allocation_etree)
19    if vuart_connections_node is None:
20        vuart_connections_node = acrn_config_utilities.append_node("/acrn-config/hv/vuart_connections", None, allocation_etree)
21
22    connection_name = service_vm_name + "_"  + user_vm_name
23
24    vuart_connection_node = acrn_config_utilities.append_node(f"./vuart_connection", None, vuart_connections_node)
25    acrn_config_utilities.append_node(f"./name", connection_name, vuart_connection_node)
26    acrn_config_utilities.append_node(f"./type", "legacy", vuart_connection_node)
27
28    service_vm_endpoint = acrn_config_utilities.append_node(f"./endpoint", None, vuart_connection_node)
29    acrn_config_utilities.append_node(f"./vm_name", service_vm_name, service_vm_endpoint)
30    acrn_config_utilities.append_node(f"./io_port", service_vm_port, service_vm_endpoint)
31
32    user_vm_endpoint = acrn_config_utilities.append_node(f"./endpoint", None, vuart_connection_node)
33    acrn_config_utilities.append_node(f"./vm_name", user_vm_name, user_vm_endpoint)
34    acrn_config_utilities.append_node(f"./io_port", user_vm_port, user_vm_endpoint)
35
36def get_console_vuart_port(scenario_etree, vm_name):
37    port = get_node(f"//vm[name = '{vm_name}']/console_vuart/text()", scenario_etree)
38
39    if port == "COM Port 1":
40        port = "0x3F8U"
41    elif port == "COM Port 2":
42        port = "0x2F8U"
43    elif port == "COM Port 3":
44        port = "0x3E8U"
45    elif port == "COM Port 4":
46        port = "0x2E8U"
47    else:
48        port = "0x0U"
49
50    return port
51
52def alloc_free_port(scenario_etree, load_order, vm_name):
53    port_list = scenario_etree.xpath(f"//endpoint[vm_name = '{vm_name}']/io_port/text()")
54    if load_order == "SERVICE_VM":
55        vm_id = int(get_node(f"//vm[load_order = 'SERVICE_VM']/@id", scenario_etree))
56    else:
57        vm_id = int(get_node(f"//vm[name = '{vm_name}']/@id", scenario_etree))
58    console_port = get_console_vuart_port(scenario_etree, vm_name)
59    if console_port is not None:
60        port_list.append(console_port.replace("U", ""))
61
62    tmp_list = []
63    for port in port_list:
64        tmp_list.append(int(port, 16))
65
66
67    global vm_port_list
68    vm_port_list[vm_id] = list(set(vm_port_list[vm_id]) - set(tmp_list))
69    vm_port_list[vm_id].sort()
70    port = hex(vm_port_list[vm_id][0])
71    vm_port_list[vm_id].remove(vm_port_list[vm_id][0])
72    return str(port).upper()
73
74def alloc_vuart_connection_info(board_etree, scenario_etree, allocation_etree):
75    user_vm_list = scenario_etree.xpath(f"//vm[load_order != 'SERVICE_VM']")
76    service_vm_id = get_node(f"//vm[load_order = 'SERVICE_VM']/@id", scenario_etree)
77    service_vm_name = get_node(f"//vm[load_order = 'SERVICE_VM']/name/text()", scenario_etree)
78
79    if (service_vm_id is None) or (service_vm_name is None):
80        return
81
82    for index,vm_node in enumerate(user_vm_list):
83        vm_id = get_node("./@id", vm_node)
84        load_order = get_node("./load_order/text()", vm_node)
85        user_vm_name = get_node(f"./name/text()", vm_node)
86        service_vm_port = alloc_free_port(scenario_etree, "SERVICE_VM", user_vm_name)
87        user_vm_port = alloc_free_port(scenario_etree, load_order, user_vm_name)
88
89        create_s5_vuart_connection(allocation_etree, service_vm_name, service_vm_port, user_vm_name, user_vm_port)
90
91def fn(board_etree, scenario_etree, allocation_etree):
92    alloc_vuart_connection_info(board_etree, scenario_etree, allocation_etree)
93