Module Name: src Committed By: martin Date: Fri Sep 15 13:25:34 UTC 2017
Modified Files: src/sys/arch/sparc/stand/ofwboot: Locore.c boot.c boot.h ofdev.c openfirm.h version src/sys/arch/sparc64/include: bootinfo.h Log Message: Add more details about the boot device as a new bootinfo record type. >From within the bootloader, when we have readily accessible instance handles of the boot device, it is easy to query more details like SCSI LUN, target, and FC-AL wwn from the firmware. The kernel later would have a hard time getting theses, but can make good use to match the boot device. To generate a diff of this commit: cvs rdiff -u -r1.15 -r1.16 src/sys/arch/sparc/stand/ofwboot/Locore.c cvs rdiff -u -r1.34 -r1.35 src/sys/arch/sparc/stand/ofwboot/boot.c cvs rdiff -u -r1.10 -r1.11 src/sys/arch/sparc/stand/ofwboot/boot.h cvs rdiff -u -r1.36 -r1.37 src/sys/arch/sparc/stand/ofwboot/ofdev.c cvs rdiff -u -r1.5 -r1.6 src/sys/arch/sparc/stand/ofwboot/openfirm.h cvs rdiff -u -r1.22 -r1.23 src/sys/arch/sparc/stand/ofwboot/version cvs rdiff -u -r1.7 -r1.8 src/sys/arch/sparc64/include/bootinfo.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/sparc/stand/ofwboot/Locore.c diff -u src/sys/arch/sparc/stand/ofwboot/Locore.c:1.15 src/sys/arch/sparc/stand/ofwboot/Locore.c:1.16 --- src/sys/arch/sparc/stand/ofwboot/Locore.c:1.15 Sat Oct 10 06:50:25 2015 +++ src/sys/arch/sparc/stand/ofwboot/Locore.c Fri Sep 15 13:25:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: Locore.c,v 1.15 2015/10/10 06:50:25 martin Exp $ */ +/* $NetBSD: Locore.c,v 1.16 2017/09/15 13:25:34 martin Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -35,6 +35,7 @@ #include "openfirm.h" #include <machine/cpu.h> +#include <machine/vmparam.h> /* * We are trying to boot a sparc v9 cpu, so openfirmware has to be 64bit, @@ -154,6 +155,26 @@ OF_instance_to_path(int ihandle, char *b } int +OF_parent(int phandle) +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t phandle; + cell_t parent; + } args; + + args.name = ADR2CELL("parent"); + args.nargs = 1; + args.nreturns = 1; + args.phandle = HDL2CELL(phandle); + if (openfirmware(&args) == -1) + return 0; + return args.parent; +} + +int OF_getprop(int handle, const char *prop, void *buf, int buflen) { struct { @@ -208,6 +229,66 @@ OF_setprop(u_int handle, char *prop, voi #endif int +OF_interpret(const char *cmd, int nargs, int nreturns, ...) +{ + va_list ap; + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t slot[16]; + } args; + cell_t status; + int i = 0; + + args.name = ADR2CELL("interpret"); + args.nargs = ++nargs; + args.nreturns = ++nreturns; + args.slot[i++] = ADR2CELL(cmd); + va_start(ap, nreturns); + while (i < nargs) { + args.slot[i++] = va_arg(ap, cell_t); + } + if (openfirmware(&args) == -1) { + va_end(ap); + return (-1); + } + status = args.slot[i++]; + while (i < nargs+nreturns) { + *va_arg(ap, cell_t *) = args.slot[i++]; + } + va_end(ap); + + return status; +} + +int +OF_package_to_path(int phandle, char *buf, int buflen) +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t phandle; + cell_t buf; + cell_t buflen; + cell_t length; + } args; + + if (buflen > PAGE_SIZE) + return -1; + args.name = ADR2CELL("package-to-path"); + args.nargs = 3; + args.nreturns = 1; + args.phandle = HDL2CELL(phandle); + args.buf = ADR2CELL(buf); + args.buflen = buflen; + if (openfirmware(&args) < 0) + return -1; + return args.length; +} + +int OF_open(const char *dname) { struct { Index: src/sys/arch/sparc/stand/ofwboot/boot.c diff -u src/sys/arch/sparc/stand/ofwboot/boot.c:1.34 src/sys/arch/sparc/stand/ofwboot/boot.c:1.35 --- src/sys/arch/sparc/stand/ofwboot/boot.c:1.34 Wed Aug 31 16:24:34 2016 +++ src/sys/arch/sparc/stand/ofwboot/boot.c Fri Sep 15 13:25:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: boot.c,v 1.34 2016/08/31 16:24:34 martin Exp $ */ +/* $NetBSD: boot.c,v 1.35 2017/09/15 13:25:34 martin Exp $ */ /* * Copyright (c) 1997, 1999 Eduardo E. Horvath. All rights reserved. @@ -284,6 +284,9 @@ jump_to_kernel(u_long *marks, char *kern bi_add(&bi_kend, BTINFO_KERNEND, sizeof(bi_kend)); bi_howto.boothowto = boothowto; bi_add(&bi_howto, BTINFO_BOOTHOWTO, sizeof(bi_howto)); + if (bootinfo_pass_bootunit) + bi_add(&bi_unit, BTINFO_BOOTDEV_UNIT, + sizeof(bi_unit)); if (bootinfo_pass_bootdev) { struct { struct btinfo_common common; Index: src/sys/arch/sparc/stand/ofwboot/boot.h diff -u src/sys/arch/sparc/stand/ofwboot/boot.h:1.10 src/sys/arch/sparc/stand/ofwboot/boot.h:1.11 --- src/sys/arch/sparc/stand/ofwboot/boot.h:1.10 Thu Feb 20 14:50:39 2014 +++ src/sys/arch/sparc/stand/ofwboot/boot.h Fri Sep 15 13:25:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: boot.h,v 1.10 2014/02/20 14:50:39 joerg Exp $ */ +/* $NetBSD: boot.h,v 1.11 2017/09/15 13:25:34 martin Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -67,6 +67,9 @@ void loadfile_set_allocator(int); void freeall(void); /* ofdev.c */ +extern struct btinfo_bootdev_unit bi_unit; +extern bool bootinfo_pass_bootunit; + char *filename(char *, char *); /* boot.c */ Index: src/sys/arch/sparc/stand/ofwboot/ofdev.c diff -u src/sys/arch/sparc/stand/ofwboot/ofdev.c:1.36 src/sys/arch/sparc/stand/ofwboot/ofdev.c:1.37 --- src/sys/arch/sparc/stand/ofwboot/ofdev.c:1.36 Sat Mar 25 09:21:21 2017 +++ src/sys/arch/sparc/stand/ofwboot/ofdev.c Fri Sep 15 13:25:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ofdev.c,v 1.36 2017/03/25 09:21:21 martin Exp $ */ +/* $NetBSD: ofdev.c,v 1.37 2017/09/15 13:25:34 martin Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -61,6 +61,9 @@ extern char bootdev[]; extern bool root_fs_quickseekable; +struct btinfo_bootdev_unit bi_unit; +bool bootinfo_pass_bootunit = false; + /* * This is ugly. A path on a sparc machine is something like this: * @@ -358,6 +361,69 @@ search_label(struct of_dev *devp, u_long return ("no disk label"); } +static void +device_target_unit(const char *dev, int ihandle) +{ + cell_t units[4], phandle, myself, depth = 0, odepth = 0, cnt; + char buf[256]; + + /* init the data passed to the kernel */ + bootinfo_pass_bootunit = false; + memset(&bi_unit, 0, sizeof(bi_unit)); + + /* save old my-self value */ + OF_interpret("my-self", 0, 1, &myself); + /* set our device as my-self */ + OF_interpret("to my-self", 1, 0, HDL2CELL(ihandle)); + + /* + * my-unit delivers a variable number of cells, we could + * walk up the path and find a #address-cells value that + * describes it, but it seems to just work this simple + * way. + */ + OF_interpret("depth", 0, 1, &odepth); + OF_interpret("my-unit depth", 0, 5, &depth, + &units[0], &units[1], &units[2], &units[3]); + cnt = depth-odepth; + + /* + * Old versions of QEMU's OpenBIOS have a bug in the + * CIF implementation for instance_to_package, test + * for that explicitly here and work around it if needed. + */ + phandle = OF_instance_to_package(ihandle); + OF_package_to_path(phandle, buf, sizeof(buf)); + buf[sizeof(buf)-1] = 0; + if (strlen(buf) > 2 && strlen(dev) > 2 && + strncmp(buf, dev, strlen(buf)) != 0) { + DPRINTF(("OpenBIOS workaround: phandle %" PRIx32 "is %s, " + "does not match %s\n", (uint32_t)phandle, buf, dev)); + OF_interpret("my-self ihandle>non-interposed-phandle", + 0, 1, &phandle); + OF_package_to_path(phandle, buf, sizeof(buf)); + DPRINTF(("new phandle %" PRIx32 " is %s\n", + (uint32_t)phandle, buf)); + } + + bi_unit.phandle = phandle; + bi_unit.parent = OF_parent(phandle); + bi_unit.lun = units[cnt > 2 ? 3 : 1]; + bi_unit.target = units[cnt > 2 ? 2 : 0]; + if (cnt >= 4) + bi_unit.wwn = (uint64_t)units[0] << 32 | (uint32_t)units[1]; + DPRINTF(("boot device package: %" PRIx32 ", parent: %" PRIx32 + ", lun: %" PRIu32 ", target: %" PRIu32 ", wwn: %" PRIx64 "\n", + bi_unit.phandle, bi_unit.parent, bi_unit.lun, bi_unit.target, + bi_unit.wwn)); + + /* restore my-self */ + OF_interpret("to my-self", 1, 0, myself); + + /* now that we have gatherd all the details, pass them to the kernel */ + bootinfo_pass_bootunit = true; +} + int devopen(struct open_file *of, const char *name, char **file) { @@ -373,6 +439,7 @@ devopen(struct open_file *of, const char size_t readsize; char *errmsg = NULL, *pp = NULL, savedpart = 0; int error = 0; + bool get_target_unit = false; if (ofdev.handle != -1) panic("devopen: ofdev already in use"); @@ -412,6 +479,9 @@ devopen(struct open_file *of, const char return ENXIO; DPRINTF(("devopen: %s is a %s device\n", fname, b.buf)); if (strcmp(b.buf, "block") == 0 || strcmp(b.buf, "scsi") == 0) { + + get_target_unit = true; + pp = strrchr(fname, ':'); if (pp && pp[1] >= 'a' && pp[1] <= 'f' && pp[2] == 0) { savedpart = pp[1]; @@ -458,6 +528,10 @@ open_again: return ENXIO; } DPRINTF(("devopen: %s is now open\n", fname)); + + if (get_target_unit) + device_target_unit(fname, handle); + memset(&ofdev, 0, sizeof ofdev); ofdev.handle = handle; if (strcmp(b.buf, "block") == 0 || strcmp(b.buf, "scsi") == 0) { Index: src/sys/arch/sparc/stand/ofwboot/openfirm.h diff -u src/sys/arch/sparc/stand/ofwboot/openfirm.h:1.5 src/sys/arch/sparc/stand/ofwboot/openfirm.h:1.6 --- src/sys/arch/sparc/stand/ofwboot/openfirm.h:1.5 Sat May 21 15:50:42 2011 +++ src/sys/arch/sparc/stand/ofwboot/openfirm.h Fri Sep 15 13:25:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: openfirm.h,v 1.5 2011/05/21 15:50:42 tsutsui Exp $ */ +/* $NetBSD: openfirm.h,v 1.6 2017/09/15 13:25:34 martin Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -70,4 +70,5 @@ vaddr_t OF_map_phys(paddr_t, off_t, vadd paddr_t OF_alloc_phys(int, int); paddr_t OF_claim_phys(paddr_t, int); int OF_free_phys(paddr_t, int); +int OF_interpret(const char *, int, int, ...); void OF_initialize(void); Index: src/sys/arch/sparc/stand/ofwboot/version diff -u src/sys/arch/sparc/stand/ofwboot/version:1.22 src/sys/arch/sparc/stand/ofwboot/version:1.23 --- src/sys/arch/sparc/stand/ofwboot/version:1.22 Sat Mar 25 09:22:02 2017 +++ src/sys/arch/sparc/stand/ofwboot/version Fri Sep 15 13:25:34 2017 @@ -1,4 +1,4 @@ -$NetBSD: version,v 1.22 2017/03/25 09:22:02 martin Exp $ +$NetBSD: version,v 1.23 2017/09/15 13:25:34 martin Exp $ NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this file is important - make sure the entries are appended on end, last item @@ -23,3 +23,4 @@ is taken as the current. 1.17: Add support for sun4v architecture 1.18: Fix loading of kernels with huge .bss 1.19: Support booting from virtio devices +1.20: Provide more boot device details Index: src/sys/arch/sparc64/include/bootinfo.h diff -u src/sys/arch/sparc64/include/bootinfo.h:1.7 src/sys/arch/sparc64/include/bootinfo.h:1.8 --- src/sys/arch/sparc64/include/bootinfo.h:1.7 Mon May 28 21:09:52 2012 +++ src/sys/arch/sparc64/include/bootinfo.h Fri Sep 15 13:25:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: bootinfo.h,v 1.7 2012/05/28 21:09:52 martin Exp $ */ +/* $NetBSD: bootinfo.h,v 1.8 2017/09/15 13:25:34 martin Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -98,6 +98,7 @@ #define BTINFO_ITLB 103 #define BTINFO_KERNEND 104 #define BTINFO_BOOTDEV 105 +#define BTINFO_BOOTDEV_UNIT 106 #define LOOKUP_BOOTINFO(btp, info) \ do { \ @@ -131,4 +132,13 @@ struct btinfo_bootdev { char name[1]; }; +struct btinfo_bootdev_unit { + struct btinfo_common common; + uint32_t phandle; /* the boot path package handle */ + uint32_t parent; /* the controller handle */ + uint32_t lun; /* scsi address details */ + uint32_t target; /* or primary/secondary channel for IDE */ + uint64_t wwn; /* zero for non FC-AL drives */ +}; + #endif /* _BOOTINFO_H_ */