From 01b635de81042a5aa80bb211e5265e2b18a8caf2 Mon Sep 17 00:00:00 2001 From: "Brian J. Johnson" Date: Wed, 25 Aug 2004 17:30:26 +0000 Subject: [PATCH] [IA64-SGI] Add full PROM version banner to /proc/sgi_prominfo/nodeXX/version. Signed-off-by: Brian J. Johnson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/sn2/prominfo_proc.c | 74 ++++++++++++++++++++----- 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c index bcc938b288384..d9228584d8cc0 100644 --- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c +++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c @@ -3,10 +3,10 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1999,2001-2004 Silicon Graphics, Inc. All Rights Reserved. * * Module to export the system's Firmware Interface Tables, including - * PROM revision numbers, in /proc + * PROM revision numbers and banners, in /proc */ #include #include @@ -45,9 +45,18 @@ MODULE_LICENSE("GPL"); # define TRACE() #endif +/* Architected IA64 firmware space */ +#define FW_BASE 0x00000000FF000000 +#define FW_TOP 0x0000000100000000 + /* Sub-regions determined by bits in Node Offset */ #define LB_PROM_SPACE 0x0000000700000000ul /* Local LB PROM */ +/* Offset of PROM banner pointers in SAL A and SAL B */ +#define SAL_A_BANNER_OFFSET (1 * 16) +#define SAL_B_BANNER_OFFSET (3 * 16) + + #define FIT_SIGNATURE 0x2020205f5449465ful /* Standard Intel FIT entry types */ #define FIT_ENTRY_FIT_HEADER 0x00 /* FIT header entry */ @@ -125,6 +134,26 @@ fit_type_name(unsigned char type) return "Unknown type"; } +static unsigned long +convert_fw_addr(nasid_t nasid, unsigned long addr) +{ + /* snag just the node-relative offset */ + addr &= ~0ul >> (63-35); + /* the pointer to SAL A is relative to IA-64 compatibility + * space. However, the PROM is mapped at a different offset + * in MMR space (both local and global) + */ + addr += 0x700000000; + return GLOBAL_MMR_ADDR(nasid, addr); +} + +static int +valid_fw_addr(unsigned long addr) +{ + addr &= ~(1ul << 63); /* Clear cached/uncached bit */ + return (addr >= FW_BASE && addr < FW_TOP); +} + /* These two routines read the FIT table directly from the FLASH PROM * on a specific node. The PROM can only be accessed using aligned 64 * bit reads, so we do that and then shift and mask the result to get @@ -194,6 +223,8 @@ dump_version(char *page, unsigned long *fit) int nentries; int fentry; unsigned long qw; + int len; + nasid_t nasid = NASID_GET(fit); TRACE(); @@ -203,10 +234,31 @@ dump_version(char *page, unsigned long *fit) for (fentry = 0; fentry < nentries; fentry++) { qw = readq(fit + 2 * fentry + 1); if (FIT_TYPE(qw) == FIT_ENTRY_SAL_A) - return sprintf(page, "%x.%02x\n", - FIT_MAJOR(qw), FIT_MINOR(qw)); + break; } - return 0; + if (fentry >= nentries) + return 0; + + len = sprintf(page, "%x.%02x\n", FIT_MAJOR(qw), FIT_MINOR(qw)); + page += len; + + qw = readq(fit + 2 * fentry); /* Address of SAL A */ + DPRINTK("SAL A at %p\n", (void *)qw); + if (!valid_fw_addr(qw)) + return len; + + qw += SAL_A_BANNER_OFFSET; + qw = convert_fw_addr(nasid, qw); + DPRINTK("Banner ptr at %p\n", (void *)qw); + + qw = readq(qw); /* Address of banner */ + if (!valid_fw_addr(qw)) + return len; + qw = convert_fw_addr(nasid, qw); + DPRINTK("Banner at %p\n", (void *)qw); + + len += snprintf(page, PAGE_SIZE-len, "%s\n", (char *)qw); + return len; } /* same as in proc_misc.c */ @@ -278,14 +330,10 @@ lookup_fit(int nasid) DPRINTK("pointer to fit at %p\n", (void *)fitp); fit_paddr = readq(fitp); DPRINTK("fit pointer contains %lx\n", fit_paddr); - /* snag just the node-relative offset */ - fit_paddr &= ~0ul >> (63-35); - /* the pointer to the FIT is relative to IA-64 compatibility - * space. However, the PROM is mapped at a different offset - * in MMR space (both local and global) - */ - fit_paddr += 0x700000000; - fit_vaddr = (void *)GLOBAL_MMR_ADDR(nasid, fit_paddr); + + BUG_ON(!valid_fw_addr(fit_paddr)); + fit_vaddr = (void *)convert_fw_addr(nasid, fit_paddr); + DPRINTK("fit at %p\n", (void *)fit_vaddr); return fit_vaddr; } -- 2.53.0