Annotation of src/sys/stand/efiboot/efifdt.c, Revision 1.7.2.2
1.7.2.2 ! pgoyette 1: /* $NetBSD: efifdt.c,v 1.7 2018/09/03 00:17:00 jmcneill Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 19: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 26: * SUCH DAMAGE.
! 27: */
! 28:
! 29: #include "efiboot.h"
! 30: #include "efifdt.h"
! 31: #include "efiblock.h"
! 32:
! 33: #include <libfdt.h>
! 34:
! 35: #define FDT_TABLE_GUID \
! 36: { 0xb1b621d5, 0xf19c, 0x41a5, { 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 } }
! 37: static EFI_GUID FdtTableGuid = FDT_TABLE_GUID;
! 38:
! 39: #define FDT_MEMORY_NODE_PATH "/memory"
! 40: #define FDT_MEMORY_NODE_NAME "memory"
! 41: #define FDT_CHOSEN_NODE_PATH "/chosen"
! 42: #define FDT_CHOSEN_NODE_NAME "chosen"
! 43:
! 44: #define FDT_MEMORY_USABLE(_md) \
! 45: ((_md)->Type == EfiLoaderCode || (_md)->Type == EfiLoaderData || \
! 46: (_md)->Type == EfiBootServicesCode || (_md)->Type == EfiBootServicesData || \
! 47: (_md)->Type == EfiConventionalMemory)
! 48:
! 49: static void *fdt_data = NULL;
! 50:
! 51: int
! 52: efi_fdt_probe(void)
! 53: {
! 54: EFI_STATUS status;
! 55:
! 56: status = LibGetSystemConfigurationTable(&FdtTableGuid, &fdt_data);
! 57: if (EFI_ERROR(status))
! 58: return EIO;
! 59:
! 60: if (fdt_check_header(fdt_data) != 0) {
! 61: fdt_data = NULL;
! 62: return EINVAL;
! 63: }
! 64:
! 65: return 0;
! 66: }
! 67:
! 68: void *
! 69: efi_fdt_data(void)
! 70: {
! 71: return fdt_data;
! 72: }
! 73:
! 74: int
! 75: efi_fdt_size(void)
! 76: {
! 77: return fdt_data == NULL ? 0 : fdt_totalsize(fdt_data);
! 78: }
! 79:
! 80: void
! 81: efi_fdt_show(void)
! 82: {
! 83: const char *model, *compat;
! 84: int n, ncompat;
! 85:
! 86: if (fdt_data == NULL)
! 87: return;
! 88:
! 89: model = fdt_getprop(fdt_data, fdt_path_offset(fdt_data, "/"), "model", NULL);
! 90: if (model)
! 91: printf("FDT: %s [", model);
! 92: ncompat = fdt_stringlist_count(fdt_data, fdt_path_offset(fdt_data, "/"), "compatible");
! 93: for (n = 0; n < ncompat; n++) {
! 94: compat = fdt_stringlist_get(fdt_data, fdt_path_offset(fdt_data, "/"),
! 95: "compatible", n, NULL);
! 96: printf("%s%s", n == 0 ? "" : ", ", compat);
! 97: }
! 98: printf("]\n");
! 99: }
! 100:
! 101: void
! 102: efi_fdt_memory_map(void)
! 103: {
! 104: UINTN nentries = 0, mapkey, descsize;
! 105: EFI_MEMORY_DESCRIPTOR *md, *memmap;
! 106: UINT32 descver;
! 107: UINT64 phys_start, phys_size;
! 108: int n, memory;
! 109:
! 110: memory = fdt_path_offset(fdt_data, FDT_MEMORY_NODE_PATH);
! 111: if (memory < 0)
! 112: memory = fdt_add_subnode(fdt_data, fdt_path_offset(fdt_data, "/"), FDT_MEMORY_NODE_NAME);
! 113: if (memory < 0)
! 114: panic("FDT: Failed to create " FDT_MEMORY_NODE_PATH " node");
! 115:
! 116: fdt_delprop(fdt_data, memory, "reg");
! 117: while (fdt_num_mem_rsv(fdt_data) > 0) {
! 118: if (fdt_del_mem_rsv(fdt_data, 0) < 0)
! 119: panic("FDT: Failed to remove reserved memory map entry");
! 120: }
! 121:
! 122: const int address_cells = fdt_address_cells(fdt_data, fdt_path_offset(fdt_data, "/"));
! 123: const int size_cells = fdt_size_cells(fdt_data, fdt_path_offset(fdt_data, "/"));
! 124:
! 125: memmap = LibMemoryMap(&nentries, &mapkey, &descsize, &descver);
! 126: for (n = 0, md = memmap; n < nentries; n++, md = NextMemoryDescriptor(md, descsize)) {
! 127: #ifdef EFI_MEMORY_DEBUG
! 128: printf("MEM: %u: Type 0x%x Attr 0x%lx Phys 0x%lx Virt 0x%lx Size 0x%lx\n",
! 129: n, md->Type, md->Attribute,
! 130: md->PhysicalStart, md->VirtualStart,
! 131: (u_long)md->NumberOfPages * EFI_PAGE_SIZE);
! 132: #endif
! 133: if ((md->Attribute & EFI_MEMORY_WB) == 0)
! 134: continue;
! 135: if (!FDT_MEMORY_USABLE(md))
! 136: continue;
! 137: if ((address_cells == 1 || size_cells == 1) && md->PhysicalStart + (md->NumberOfPages * EFI_PAGE_SIZE) > 0xffffffff)
! 138: continue;
! 139: if (md->NumberOfPages <= 1)
! 140: continue;
! 141:
! 142: phys_start = md->PhysicalStart;
! 143: phys_size = md->NumberOfPages * EFI_PAGE_SIZE;
! 144:
! 145: if (phys_start & EFI_PAGE_MASK) {
! 146: /* UEFI spec says these should be 4KB aligned, but U-Boot doesn't always.. */
! 147: phys_start = (phys_start + EFI_PAGE_SIZE) & ~EFI_PAGE_MASK;
! 148: phys_size -= (EFI_PAGE_SIZE * 2);
! 149: if (phys_size == 0)
! 150: continue;
! 151: }
! 152:
! 153: if (address_cells == 1)
! 154: fdt_appendprop_u32(fdt_data, fdt_path_offset(fdt_data, FDT_MEMORY_NODE_PATH),
! 155: "reg", (uint32_t)phys_start);
! 156: else
! 157: fdt_appendprop_u64(fdt_data, fdt_path_offset(fdt_data, FDT_MEMORY_NODE_PATH),
! 158: "reg", phys_start);
! 159:
! 160: if (size_cells == 1)
! 161: fdt_appendprop_u32(fdt_data, fdt_path_offset(fdt_data, FDT_MEMORY_NODE_PATH),
! 162: "reg", (uint32_t)phys_size);
! 163: else
! 164: fdt_appendprop_u64(fdt_data, fdt_path_offset(fdt_data, FDT_MEMORY_NODE_PATH),
! 165: "reg", phys_size);
! 166: }
! 167: }
! 168:
! 169: void
! 170: efi_fdt_bootargs(const char *bootargs)
! 171: {
! 172: struct efi_block_part *bpart = efi_block_boot_part();
! 173: int chosen;
! 174:
! 175: chosen = fdt_path_offset(fdt_data, FDT_CHOSEN_NODE_PATH);
! 176: if (chosen < 0)
! 177: chosen = fdt_add_subnode(fdt_data, fdt_path_offset(fdt_data, "/"), FDT_CHOSEN_NODE_NAME);
! 178: if (chosen < 0)
! 179: panic("FDT: Failed to create " FDT_CHOSEN_NODE_PATH " node");
! 180:
! 181: if (*bootargs)
! 182: fdt_setprop_string(fdt_data, chosen, "bootargs", bootargs);
! 183:
! 184: if (bpart) {
! 185: switch (bpart->type) {
! 186: case EFI_BLOCK_PART_DISKLABEL:
! 187: fdt_setprop(fdt_data, chosen, "netbsd,mbr",
! 188: bpart->hash, sizeof(bpart->hash));
! 189: fdt_setprop_u32(fdt_data, chosen, "netbsd,partition",
! 190: bpart->index);
! 191: break;
! 192: default:
! 193: break;
! 194: }
! 195: }
! 196: }
CVSweb <webmaster@jp.NetBSD.org>