From owner-svn-src-head@FreeBSD.ORG Fri Nov 30 03:15:50 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 8A7B017C; Fri, 30 Nov 2012 03:15:50 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 6EB588FC13; Fri, 30 Nov 2012 03:15:50 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qAU3Fo9q006255; Fri, 30 Nov 2012 03:15:50 GMT (envelope-from gonzo@svn.freebsd.org) Received: (from gonzo@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qAU3FoRU006253; Fri, 30 Nov 2012 03:15:50 GMT (envelope-from gonzo@svn.freebsd.org) Message-Id: <201211300315.qAU3FoRU006253@svn.freebsd.org> From: Oleksandr Tymoshenko Date: Fri, 30 Nov 2012 03:15:50 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r243693 - in head/sys/boot: fdt uboot/common X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 30 Nov 2012 03:15:50 -0000 Author: gonzo Date: Fri Nov 30 03:15:50 2012 New Revision: 243693 URL: http://svnweb.freebsd.org/changeset/base/243693 Log: - Implement "fdt mres" sub-command that prints reserved memory regions - Add "fdt addr" subcommand that lets you specify preloaded blob address - Do not pre-initialize blob for "fdt addr" - Do not try to load dtb every time fdt subcommand is issued, do it only once - Change the way DTB is passed to kernel. With introduction of "fdt addr" actual blob address can be not virtual but physical or reside in area higher then 64Mb. ubldr should create copy of it in kernel area and pass pointer to this newly allocated buffer which is guaranteed to work in kernel after switching on MMU. - Convert memreserv FDT info to "memreserv" property of root node FDT uses /memreserve/ data to notify OS about reserved memory areas. Technically it's not real property, it's just data blob, sequence of pairs where both start and size are 64-bit integers. It doesn't fit nicely with OF API we use in kernel, so in order to unify thing ubldr converts this data to "memreserve" property using the same format for addresses and sizes as /memory node. Modified: head/sys/boot/fdt/fdt_loader_cmd.c head/sys/boot/uboot/common/metadata.c Modified: head/sys/boot/fdt/fdt_loader_cmd.c ============================================================================== --- head/sys/boot/fdt/fdt_loader_cmd.c Fri Nov 30 03:14:11 2012 (r243692) +++ head/sys/boot/fdt/fdt_loader_cmd.c Fri Nov 30 03:15:50 2012 (r243693) @@ -40,8 +40,6 @@ __FBSDID("$FreeBSD$"); #include "bootstrap.h" #include "glue.h" -#define DEBUG - #ifdef DEBUG #define debugf(fmt, args...) do { printf("%s(): ", __func__); \ printf(fmt,##args); } while (0) @@ -62,6 +60,8 @@ __FBSDID("$FreeBSD$"); #define FDT_STATIC_DTB_SYMBOL "fdt_static_dtb" +#define CMD_REQUIRES_BLOB 0x01 + /* Local copy of FDT */ static struct fdt_header *fdtp = NULL; /* Size of FDT blob */ @@ -69,8 +69,11 @@ static size_t fdtp_size = 0; /* Location of FDT in kernel or module */ static vm_offset_t fdtp_va = 0; +static int fdt_load_dtb(vm_offset_t va); + static int fdt_cmd_nyi(int argc, char *argv[]); +static int fdt_cmd_addr(int argc, char *argv[]); static int fdt_cmd_mkprop(int argc, char *argv[]); static int fdt_cmd_cd(int argc, char *argv[]); static int fdt_cmd_hdr(int argc, char *argv[]); @@ -79,25 +82,28 @@ static int fdt_cmd_prop(int argc, char * static int fdt_cmd_pwd(int argc, char *argv[]); static int fdt_cmd_rm(int argc, char *argv[]); static int fdt_cmd_mknode(int argc, char *argv[]); +static int fdt_cmd_mres(int argc, char *argv[]); typedef int cmdf_t(int, char *[]); struct cmdtab { char *name; cmdf_t *handler; + int flags; }; static const struct cmdtab commands[] = { - { "alias", &fdt_cmd_nyi }, - { "cd", &fdt_cmd_cd }, - { "header", &fdt_cmd_hdr }, - { "ls", &fdt_cmd_ls }, - { "mknode", &fdt_cmd_mknode }, - { "mkprop", &fdt_cmd_mkprop }, - { "mres", &fdt_cmd_nyi }, - { "prop", &fdt_cmd_prop }, - { "pwd", &fdt_cmd_pwd }, - { "rm", &fdt_cmd_rm }, + { "addr", &fdt_cmd_addr, 0 }, + { "alias", &fdt_cmd_nyi, 0 }, + { "cd", &fdt_cmd_cd, CMD_REQUIRES_BLOB }, + { "header", &fdt_cmd_hdr, CMD_REQUIRES_BLOB }, + { "ls", &fdt_cmd_ls, CMD_REQUIRES_BLOB }, + { "mknode", &fdt_cmd_mknode, CMD_REQUIRES_BLOB }, + { "mkprop", &fdt_cmd_mkprop, CMD_REQUIRES_BLOB }, + { "mres", &fdt_cmd_mres, CMD_REQUIRES_BLOB }, + { "prop", &fdt_cmd_prop, CMD_REQUIRES_BLOB }, + { "pwd", &fdt_cmd_pwd, CMD_REQUIRES_BLOB }, + { "rm", &fdt_cmd_rm, CMD_REQUIRES_BLOB }, { NULL, NULL } }; @@ -128,7 +134,7 @@ fdt_find_static_dtb() if (md == NULL) return (0); bcopy(md->md_data, &esym, sizeof(esym)); - // esym is already offset + /* esym is already offset */ md = file_findmetadata(kfp, MODINFOMD_DYNAMIC); if (md == NULL) @@ -188,53 +194,67 @@ fdt_find_static_dtb() } static int -fdt_setup_fdtp() +fdt_load_dtb(vm_offset_t va) { struct fdt_header header; - struct preloaded_file *bfp; int err; + COPYOUT(va, &header, sizeof(header)); + err = fdt_check_header(&header); + if (err < 0) { + if (err == -FDT_ERR_BADVERSION) + sprintf(command_errbuf, + "incompatible blob version: %d, should be: %d", + fdt_version(fdtp), FDT_LAST_SUPPORTED_VERSION); + + else + sprintf(command_errbuf, "error validating blob: %s", + fdt_strerror(err)); + return (1); + } + /* - * Find the device tree blob. + * Release previous blob */ - bfp = file_findfile(NULL, "dtb"); - if (bfp == NULL) { - if ((fdtp_va = fdt_find_static_dtb()) == 0) { - command_errmsg = "no device tree blob found!"; - printf("%s\n", command_errmsg); - return (CMD_ERROR); - } - } else { - /* Dynamic blob has precedence over static. */ - fdtp_va = bfp->f_addr; - } + if (fdtp) + free(fdtp); - COPYOUT(fdtp_va, &header, sizeof(header)); fdtp_size = fdt_totalsize(&header); fdtp = malloc(fdtp_size); + if (fdtp == NULL) { command_errmsg = "can't allocate memory for device tree copy"; - printf("%s\n", command_errmsg); - return (CMD_ERROR); + return (1); } - COPYOUT(fdtp_va, fdtp, fdtp_size); - /* - * Validate the blob. - */ - err = fdt_check_header(fdtp); - if (err < 0) { - if (err == -FDT_ERR_BADVERSION) - sprintf(command_errbuf, - "incompatible blob version: %d, should be: %d", - fdt_version(fdtp), FDT_LAST_SUPPORTED_VERSION); + fdtp_va = va; + COPYOUT(va, fdtp, fdtp_size); + debugf("DTB blob found at 0x%jx, size: 0x%jx\n", (uintmax_t)va, (uintmax_t)fdtp_size); - else - sprintf(command_errbuf, "error validating blob: %s", - fdt_strerror(err)); - return (CMD_ERROR); + return (0); +} + +static int +fdt_setup_fdtp() +{ + struct preloaded_file *bfp; + vm_offset_t va; + + bfp = file_findfile(NULL, "dtb"); + if (bfp == NULL) { + if ((va = fdt_find_static_dtb()) == 0) { + command_errmsg = "no device tree blob found!"; + return (1); + } + } else { + /* Dynamic blob has precedence over static. */ + va = bfp->f_addr; } - return (CMD_OK); + + if (fdt_load_dtb(va) != 0) + return (1); + + return (0); } #define fdt_strtovect(str, cellbuf, lim, cellsize) _fdt_strtovect((str), \ @@ -414,6 +434,8 @@ fixup_memory(struct sys_info *si) uint32_t *addr_cellsp, *reg, *size_cellsp; int err, i, len, memory, realmrno, root; uint8_t *buf, *sb; + uint64_t rstart, rsize; + int reserved; root = fdt_path_offset(fdtp, "/"); if (root < 0) { @@ -453,6 +475,52 @@ fixup_memory(struct sys_info *si) addr_cells = fdt32_to_cpu(*addr_cellsp); size_cells = fdt32_to_cpu(*size_cellsp); + /* + * Convert memreserve data to memreserve property + * Check if property already exists + */ + reserved = fdt_num_mem_rsv(fdtp); + if (reserved && + (fdt_getprop(fdtp, root, "memreserve", NULL) == NULL)) { + len = (addr_cells + size_cells) * reserved * sizeof(uint32_t); + sb = buf = (uint8_t *)malloc(len); + if (!buf) + return; + + bzero(buf, len); + + for (i = 0; i < reserved; i++) { + curmr = &si->mr[i]; + if (fdt_get_mem_rsv(fdtp, i, &rstart, &rsize)) + break; + if (rsize) { + /* Ensure endianess, and put cells into a buffer */ + if (addr_cells == 2) + *(uint64_t *)buf = + cpu_to_fdt64(rstart); + else + *(uint32_t *)buf = + cpu_to_fdt32(rstart); + + buf += sizeof(uint32_t) * addr_cells; + if (size_cells == 2) + *(uint64_t *)buf = + cpu_to_fdt64(rsize); + else + *(uint32_t *)buf = + cpu_to_fdt32(rsize); + + buf += sizeof(uint32_t) * size_cells; + } + } + + /* Set property */ + if ((err = fdt_setprop(fdtp, root, "memreserve", sb, len)) < 0) + printf("Could not fixup 'memreserve' property.\n"); + + free(sb); + } + /* Count valid memory regions entries in sysinfo. */ realmrno = si->mr_no; for (i = 0; i < si->mr_no; i++) @@ -509,6 +577,8 @@ fixup_memory(struct sys_info *si) /* Set property */ if ((err = fdt_setprop(fdtp, memory, "reg", sb, len)) < 0) sprintf(command_errbuf, "Could not fixup '/memory' node.\n"); + + free(sb); } void @@ -564,7 +634,7 @@ fixup_stdout(const char *env) /* * Locate the blob, fix it up and return its location. */ -vm_offset_t +static vm_offset_t fdt_fixup(void) { const char *env; @@ -577,10 +647,12 @@ fdt_fixup(void) ethstr = NULL; len = 0; - err = fdt_setup_fdtp(); - if (err) { - sprintf(command_errbuf, "No valid device tree blob found!"); - return (0); + if (fdtp == NULL) { + err = fdt_setup_fdtp(); + if (err) { + sprintf(command_errbuf, "No valid device tree blob found!"); + return (0); + } } /* Create /chosen node (if not exists) */ @@ -640,10 +712,36 @@ success: return (fdtp_va); } +/* + * Copy DTB blob to specified location and its return size + */ +int +fdt_copy(vm_offset_t va) +{ + int err; + + if (fdtp == NULL) { + err = fdt_setup_fdtp(); + if (err) { + printf("No valid device tree blob found!"); + return (0); + } + } + + if (fdt_fixup() == 0) + return (0); + + COPYIN(fdtp, va, fdtp_size); + return (fdtp_size); +} + + + int command_fdt_internal(int argc, char *argv[]) { cmdf_t *cmdh; + int flags; char *cmd; int i, err; @@ -653,12 +751,6 @@ command_fdt_internal(int argc, char *arg } /* - * Check if uboot env vars were parsed already. If not, do it now. - */ - if (fdt_fixup() == 0) - return (CMD_ERROR); - - /* * Validate fdt . */ cmd = strdup(argv[1]); @@ -668,6 +760,7 @@ command_fdt_internal(int argc, char *arg if (strcmp(cmd, commands[i].name) == 0) { /* found it */ cmdh = commands[i].handler; + flags = commands[i].flags; break; } i++; @@ -677,6 +770,14 @@ command_fdt_internal(int argc, char *arg return (CMD_ERROR); } + if (flags & CMD_REQUIRES_BLOB) { + /* + * Check if uboot env vars were parsed already. If not, do it now. + */ + if (fdt_fixup() == 0) + return (CMD_ERROR); + } + /* * Call command handler. */ @@ -686,6 +787,31 @@ command_fdt_internal(int argc, char *arg } static int +fdt_cmd_addr(int argc, char *argv[]) +{ + vm_offset_t va; + char *addr, *cp; + + if (argc > 2) + addr = argv[2]; + else { + sprintf(command_errbuf, "no address specified"); + return (CMD_ERROR); + } + + va = strtol(addr, &cp, 0); + if (cp == addr) { + sprintf(command_errbuf, "Invalid address: %s", addr); + return (CMD_ERROR); + } + + if (fdt_load_dtb(va) != 0) + return (CMD_ERROR); + + return (CMD_OK); +} + +static int fdt_cmd_cd(int argc, char *argv[]) { char *path; @@ -1445,6 +1571,30 @@ fdt_cmd_pwd(int argc, char *argv[]) } static int +fdt_cmd_mres(int argc, char *argv[]) +{ + uint64_t start, size; + int i, total; + char line[80]; + + pager_open(); + total = fdt_num_mem_rsv(fdtp); + if (total > 0) { + pager_output("Reserved memory regions:\n"); + for (i = 0; i < total; i++) { + fdt_get_mem_rsv(fdtp, i, &start, &size); + sprintf(line, "reg#%d: (start: 0x%jx, size: 0x%jx)\n", + i, start, size); + pager_output(line); + } + } else + pager_output("No reserved memory regions\n"); + pager_close(); + + return (CMD_OK); +} + +static int fdt_cmd_nyi(int argc, char *argv[]) { Modified: head/sys/boot/uboot/common/metadata.c ============================================================================== --- head/sys/boot/uboot/common/metadata.c Fri Nov 30 03:14:11 2012 (r243692) +++ head/sys/boot/uboot/common/metadata.c Fri Nov 30 03:15:50 2012 (r243693) @@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$"); #include "glue.h" #if defined(LOADER_FDT_SUPPORT) -extern vm_offset_t fdt_fixup(void); +extern int fdt_copy(vm_offset_t); #endif /* @@ -279,7 +279,10 @@ md_load(char *args, vm_offset_t *modulep vm_offset_t envp; vm_offset_t size; vm_offset_t vaddr; +#if defined(LOADER_FDT_SUPPORT) vm_offset_t dtbp; + int dtb_size; +#endif char *rootdevname; int howto; int i; @@ -325,6 +328,16 @@ md_load(char *args, vm_offset_t *modulep /* Pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); +#if defined(LOADER_FDT_SUPPORT) + /* Handle device tree blob */ + dtbp = addr; + dtb_size = fdt_copy(addr); + + /* Pad to a page boundary */ + if (dtb_size) + addr += roundup(dtb_size, PAGE_SIZE); +#endif + kernend = 0; kfp = file_findfile(NULL, "elf32 kernel"); if (kfp == NULL) @@ -335,9 +348,7 @@ md_load(char *args, vm_offset_t *modulep file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); #if defined(LOADER_FDT_SUPPORT) - /* Handle device tree blob */ - dtbp = fdt_fixup(); - if (dtbp != 0) + if (dtb_size) file_addmetadata(kfp, MODINFOMD_DTBP, sizeof dtbp, &dtbp); else pager_output("WARNING! Trying to fire up the kernel, but no "