Skip to content

Commit 6ff0d6d

Browse files
dt: device discovery with devicetree initial implementation
1 parent d6c5c59 commit 6ff0d6d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+7523
-34
lines changed

.clang-format

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,5 @@ ForEachMacros:
6363
- LIST4_FOREACH
6464
- LIST4_FOREACH_DELETABLE
6565
- ARRAYLIST_FOREACH
66+
- fdt_for_each_subnode
67+
- fdt_for_each_property_offset

Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,3 +474,11 @@ config DEBUG_SERIAL
474474
bool
475475
default n
476476
prompt "Debug serial for Linux early console"
477+
478+
config DEVICETREE
479+
bool
480+
default y
481+
prompt "Enable support for discovering devices with Devicetree"
482+
help
483+
If ACPI is optional or not available on the target architecture, it
484+
is recommended to set this option to 'y'.

LICENSE

Lines changed: 370 additions & 0 deletions
Large diffs are not rendered by default.

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ subdirs-$(CONFIG_VPN) += vpn
2727
subdirs-$(CONFIG_IDMAN) += idman
2828
subdirs-y += net
2929
subdirs-$(CONFIG_IP) += ip
30+
subdirs-$(CONFIG_DEVICETREE) += devtree
3031
asubdirs-$(CONFIG_CRYPTO) += crypto
3132
psubdirs-y += process
3233

boot/uefi-loader/loadvmm.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <Protocol/BlockIoCrypto.h>
3232
#include <Protocol/LoadedImage.h>
3333
#include <Protocol/SimpleFileSystem.h>
34+
#include <efi_extra/config_table.h>
3435
#include <efi_extra/device_path_helper.h>
3536
#include <uefi_boot.h>
3637

@@ -53,6 +54,8 @@ static EFI_GUID LoadedImageProtocol = EFI_LOADED_IMAGE_PROTOCOL_GUID;
5354
static EFI_GUID FileSystemProtocol = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
5455
static EFI_GUID BlockIoCryptoProtocol = EFI_BLOCK_IO_CRYPTO_PROTOCOL_GUID;
5556

57+
static EFI_GUID DtbTableGUID = EFI_DTB_TABLE_GUID;
58+
5659
static EFI_HANDLE saved_image;
5760
static EFI_SYSTEM_TABLE *saved_systab;
5861

@@ -126,6 +129,35 @@ create_file_path (EFI_DEVICE_PATH_PROTOCOL *dp, CHAR16 *newname, CHAR16 *buf,
126129
#include "bsdriver_load.h"
127130
#include "acpi_table_mod.h"
128131

132+
static BOOLEAN
133+
guid_cmp (EFI_GUID *g1, EFI_GUID *g2)
134+
{
135+
UINT64 *p1, *p2;
136+
137+
/* GUID is 128 bits. So, we can treat it as an array of UINT64. */
138+
p1 = (UINT64 *)g1;
139+
p2 = (UINT64 *)g2;
140+
141+
return p1[0] == p2[0] && p1[1] == p2[1];
142+
}
143+
144+
static BOOLEAN
145+
search_config_tab_dtb (EFI_SYSTEM_TABLE *systab, void **fdt_base)
146+
{
147+
EFI_CONFIGURATION_TABLE *ct = systab->ConfigurationTable;
148+
UINTN i, n;
149+
150+
n = systab->NumberOfTableEntries;
151+
for (i = 0; i < n; i++) {
152+
if (guid_cmp (&ct[i].VendorGuid, &DtbTableGUID)) {
153+
*fdt_base = ct[i].VendorTable;
154+
return TRUE;
155+
}
156+
}
157+
158+
return FALSE;
159+
}
160+
129161
EFI_STATUS EFIAPI
130162
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
131163
{
@@ -140,6 +172,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
140172
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fileio;
141173
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
142174
EFI_PHYSICAL_ADDRESS paddr = UPPER_LOAD_ADDR;
175+
BOOLEAN dtb_found;
143176

144177
saved_image = image;
145178
saved_systab = systab;
@@ -201,10 +234,15 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
201234
UEFI_BITVISOR_ACPI_TABLE_MOD_UUID,
202235
acpi_table_mod
203236
};
237+
struct bitvisor_devtree boot_ext4 = {
238+
UEFI_BITVISOR_DEVTREE_UUID,
239+
};
240+
dtb_found = search_config_tab_dtb (systab, &boot_ext4.fdt_base);
204241
void *boot_exts[] = {
205242
&boot_ext,
206243
&boot_ext2,
207244
&boot_ext3,
245+
dtb_found ? &boot_ext4 : NULL,
208246
NULL
209247
};
210248

core/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ CONSTANTS-$(CONFIG_ACPI_IGNORE_ERROR) += -DACPI_IGNORE_ERROR
1818

1919
CFLAGS += -I$(DIR)/include
2020
CFLAGS += -Ivpn/lib
21+
CFLAGS += -Idevtree/libfdt
2122
CFLAGS += $(CFLAGS_EDK2_INC)
2223

2324
subdirs-y += $(ARCH)
@@ -30,6 +31,7 @@ objs-y += calluefi.o
3031
objs-y += config.o
3132
objs-y += debug.o
3233
objs-y += dres.o
34+
objs-$(CONFIG_DEVICETREE) += dt.o
3335
objs-y += exint_pass.o
3436
objs-y += iccard.o
3537
objs-y += initfunc.o

core/aarch64/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
CONSTANTS-$(CONFIG_ENABLE_ASSERT) += -DENABLE_ASSERT
22
CONSTANTS-$(CONFIG_ACPI_DSDT) += -DACPI_DSDT
33
CONSTANTS-$(CONFIG_BACKTRACE) += -DBACKTRACE
4+
CONSTANTS-$(CONFIG_DEVICETREE) += -DDEVICETREE
45

56
CFLAGS += -Icore/include
67
CFLAGS += -Idevtree/libfdt

core/aarch64/gic.c

Lines changed: 164 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@
3131
#include <bits.h>
3232
#include <common.h>
3333
#include <constants.h>
34+
#include <libfdt.h>
3435
#include <core/aarch64/gic.h>
3536
#include <core/assert.h>
3637
#include <core/dres.h>
38+
#include <core/dt.h>
3739
#include <core/initfunc.h>
3840
#include <core/mm.h>
3941
#include <core/mmio.h>
@@ -43,6 +45,7 @@
4345
#include <core/spinlock.h>
4446
#include <core/types.h>
4547
#include "../acpi.h"
48+
#include "../dt.h"
4649
#include "../exint_pass.h"
4750
#include "asm.h"
4851
#include "exception.h"
@@ -1297,16 +1300,11 @@ gic_its_init (phys_t base_phys)
12971300
}
12981301

12991302
static void
1300-
acpi_madt_handle_gicd (struct acpi_ic_header *h)
1303+
gicd_init (phys_t base)
13011304
{
1302-
struct acpi_gicd *entry;
1303-
phys_t base, typer;
1305+
phys_t typer;
13041306
u32 *gicd_typer, v;
13051307

1306-
entry = (struct acpi_gicd *)h;
1307-
base = entry->phys_addr;
1308-
ASSERT (base);
1309-
13101308
typer = base + GICD_TYPER;
13111309
gicd_typer = mapmem_hphys (typer, sizeof *gicd_typer, MAPMEM_UC);
13121310
ASSERT (gicd_typer);
@@ -1334,6 +1332,19 @@ acpi_madt_handle_gicd (struct acpi_ic_header *h)
13341332
GIC_N_INITD_WATERMARK);
13351333
}
13361334

1335+
static void
1336+
acpi_madt_handle_gicd (struct acpi_ic_header *h)
1337+
{
1338+
struct acpi_gicd *entry;
1339+
phys_t base;
1340+
1341+
entry = (struct acpi_gicd *)h;
1342+
base = entry->phys_addr;
1343+
ASSERT (base);
1344+
1345+
gicd_init (base);
1346+
}
1347+
13371348
static void
13381349
acpi_madt_handle_gic_its (struct acpi_ic_header *h)
13391350
{
@@ -1382,16 +1393,156 @@ acpi_madt_walk (struct acpi_madt *m)
13821393
panic ("%s(): GIC-ITS not initialized", __func__);
13831394
}
13841395

1385-
static void
1386-
gic_init (void)
1396+
static int
1397+
gic_init_acpi (void)
13871398
{
13881399
struct acpi_madt *m;
13891400

13901401
m = acpi_find_entry (ACPI_MADT_SIGNATURE);
1391-
if (!m)
1392-
panic ("ACPI MADT not found\n");
1402+
if (m)
1403+
acpi_madt_walk (m);
1404+
1405+
return m ? 0 : -1;
1406+
}
1407+
1408+
#ifdef DEVICETREE
1409+
static int
1410+
gic_init_fdt (void)
1411+
{
1412+
struct dt_reg gicd_reg;
1413+
struct dt_reg its_reg;
1414+
const void *fdt;
1415+
const u32 *intp_p;
1416+
const void *reg;
1417+
u32 intp;
1418+
int error, intc_node, node, lenp, address_cells, size_cells;
1419+
int ret = 0;
1420+
enum dt_result_t dt_error;
1421+
1422+
fdt = dt_get_fdt ();
1423+
if (!fdt) {
1424+
ret = -1;
1425+
goto end;
1426+
}
1427+
1428+
/*
1429+
* Many DT seems to have this. Try searching for interrupt controller
1430+
* wtih this first initially.
1431+
*/
1432+
intp_p = fdt_getprop (fdt, 0, "interrupt-parent", NULL);
1433+
if (!intp_p) {
1434+
printf ("%s(): cannot find interrupt-parent property\n",
1435+
__func__);
1436+
ret = -1;
1437+
goto end;
1438+
}
1439+
1440+
intp = fdt32_ld (intp_p);
1441+
intc_node = fdt_node_offset_by_phandle (fdt, intp);
1442+
if (intc_node < 0) {
1443+
printf ("%s(): cannot find node from phandle? 0x%X %d\n",
1444+
__func__, intp, intc_node);
1445+
ret = -1;
1446+
goto end;
1447+
}
1448+
1449+
error = fdt_node_check_compatible (fdt, intc_node, "arm,gic-v3");
1450+
if (error) {
1451+
printf ("%s(): interrupt controller is not GICv3 compatible\n",
1452+
__func__);
1453+
ret = -1;
1454+
goto end;
1455+
}
1456+
1457+
/* Register's address-cells and size-cells are from the parent node */
1458+
dt_error = dt_helper_cur_node_reg_address_size_cell (fdt, intc_node,
1459+
&address_cells,
1460+
&size_cells);
1461+
if (dt_error) {
1462+
printf ("%s(): cannot read parent's address/size cells\n",
1463+
__func__);
1464+
ret = -1;
1465+
goto end;
1466+
}
1467+
1468+
reg = fdt_getprop (fdt, intc_node, "reg", &lenp);
1469+
if (!reg) {
1470+
printf ("%s(): cannot find reg property\n", __func__);
1471+
ret = -1;
1472+
goto end;
1473+
}
1474+
1475+
/* We want GICD only for now */
1476+
dt_error = dt_helper_reg_extract (reg, lenp, address_cells, size_cells,
1477+
&gicd_reg, 1);
1478+
if (dt_error) {
1479+
printf ("%s(): extract GICD reg fails\n", __func__);
1480+
ret = -1;
1481+
goto end;
1482+
}
1483+
1484+
gicd_init (gicd_reg.addr);
1485+
1486+
if (!gicd)
1487+
panic ("%s(): GICD not initialized", __func__);
1488+
1489+
/* Read address/size cells for the subnodes */
1490+
address_cells = fdt_address_cells (fdt, intc_node);
1491+
if (address_cells < 0) {
1492+
printf ("%s(): #address-cells readding error %d\n", __func__,
1493+
address_cells);
1494+
ret = -1;
1495+
goto end;
1496+
}
1497+
size_cells = fdt_size_cells (fdt, intc_node);
1498+
if (size_cells < 0) {
1499+
printf ("%s(): #size-cells readding error %d\n", __func__,
1500+
size_cells);
1501+
ret = -1;
1502+
goto end;
1503+
}
1504+
1505+
fdt_for_each_subnode (node, fdt, intc_node) {
1506+
error = fdt_node_check_compatible (fdt, node,
1507+
"arm,gic-v3-its");
1508+
if (error)
1509+
continue;
1510+
1511+
reg = fdt_getprop (fdt, node, "reg", &lenp);
1512+
if (!reg)
1513+
continue;
1514+
1515+
dt_error = dt_helper_reg_extract (reg, lenp, address_cells,
1516+
size_cells, &its_reg, 1);
1517+
if (dt_error) {
1518+
printf ("%s(): extract ITS reg fails\n", __func__);
1519+
continue;
1520+
}
1521+
gic_its_init (its_reg.addr);
1522+
}
1523+
1524+
if (!its)
1525+
panic ("%s(): GIC-ITS not initialized", __func__);
1526+
end:
1527+
return ret;
1528+
}
1529+
#endif
1530+
1531+
static void
1532+
gic_init (void)
1533+
{
1534+
int error;
1535+
1536+
error = gic_init_acpi ();
1537+
if (!error)
1538+
return;
1539+
#ifdef DEVICETREE
1540+
error = gic_init_fdt ();
1541+
if (!error)
1542+
return;
1543+
#endif
13931544

1394-
acpi_madt_walk (m);
1545+
panic ("%s(): no GIC found", __func__);
13951546
}
13961547

13971548
static void
@@ -1416,6 +1567,6 @@ gic_intr_off (void)
14161567
msr (GIC_ICC_IGRPEN1_EL1, 0x0);
14171568
}
14181569

1419-
INITFUNC ("acpi0", gic_init);
1570+
INITFUNC ("bsp0", gic_init);
14201571
INITFUNC ("pcpu0", gic_pcpu_lr_list_init);
14211572
INITFUNC ("panic_dump_done0", gic_intr_off);

core/aarch64/vm.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <core/printf.h>
3636
#include <core/spinlock.h>
3737
#include <core/string.h>
38+
#include "../dt.h"
3839
#include "../uefi.h"
3940
#include "arm_std_regs.h"
4041
#include "asm.h"
@@ -102,6 +103,9 @@ vm_start (void)
102103
p = tpidr_get_pcpu ();
103104
p->currentvcpu = new_vcpu0;
104105

106+
#ifdef DEVICETREE
107+
dt_no_more_fdt ();
108+
#endif
105109
/*
106110
* No more interacting with UEFI at this point. We are going to set up
107111
* GIC, and jump to the guest at this point.

core/aarch64/vmm.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <core/panic.h>
3333
#include <core/printf.h>
3434
#include <core/process.h>
35+
#include "../dt.h"
3536
#include "../initfunc.h"
3637
#include "../uefi.h"
3738
#include "asm.h"
@@ -83,6 +84,9 @@ vmm_main (void)
8384

8485
initfunc_init ();
8586
call_initfunc ("global");
87+
#ifdef DEVICETREE
88+
dt_init ();
89+
#endif
8690
call_initfunc ("bsp");
8791
call_parallel ();
8892
call_initfunc ("pcpu");

0 commit comments

Comments
 (0)