memswitch on /boot
Tetsuya Isaki <[email protected]> Sat, 02 Aug 2014 00:11:46 +0900
| Newsgroups | gmane.os.netbsd.ports.x68k |
|---|---|
| Message-ID | <x7ha1ww8gd.wl%[email protected]> |
Hi all, This is a patch that adds memswitch like command to /boot. The new command name is 'switch'. Of course the name was inspired from Human68k's switch.x. Other candidates that I thought are 'sram' or 'sw'... I thought that 'memswitch' is too long to enter without any shell completion and its syntax is also too complex to implement on the bootloader. This command is a subset of the original switch.x (and memswitch) that specialized for required situation. Currently only 3 parameters are supported. i.e., boot, rom, memory. These parameter names and values are also inspired from 'switch.x ?' help message (but not the same). - 'boot' and 'rom' specify the boot device/address. - 'memory' specifies the main memory size and it should match the actual installed memory size. Please look at the help message (cmd_switch_help() function in switch.c) for how to use :) Any comments? or I will commit it few days or a week after. --- Tetsuya Isaki <[email protected] / [email protected]> Index: sys/arch/x68k/stand/boot/Makefile =================================================================== RCS file: /cvsroot/src/sys/arch/x68k/stand/boot/Makefile,v retrieving revision 1.23 diff -u -r1.23 Makefile --- sys/arch/x68k/stand/boot/Makefile 6 Jul 2014 06:28:49 -0000 1.23 +++ sys/arch/x68k/stand/boot/Makefile 1 Aug 2014 09:44:12 -0000 @@ -22,7 +22,7 @@ STRIP?= /usr/bin/strip OBJCOPY?= /usr/bin/objcopy -SRCS= srt0.S boot.c conf.c exec_image.S +SRCS= srt0.S boot.c conf.c switch.c exec_image.S S= ${.CURDIR}/../../../.. M= ${.CURDIR}/../.. COMMONDIR= $M/stand/common Index: sys/arch/x68k/stand/boot/boot.c =================================================================== RCS file: /cvsroot/src/sys/arch/x68k/stand/boot/boot.c,v retrieving revision 1.21 diff -u -r1.21 boot.c --- sys/arch/x68k/stand/boot/boot.c 6 Jul 2014 08:10:21 -0000 1.21 +++ sys/arch/x68k/stand/boot/boot.c 1 Aug 2014 09:44:12 -0000 @@ -39,6 +39,7 @@ #include "libx68k.h" #include "iocs.h" +#include "switch.h" #include "exec_image.h" @@ -122,6 +123,7 @@ #ifndef NETBOOT printf("ls [dev:][directory]\n"); #endif + printf("switch [show | key=val]\n"); printf("halt\nreboot\n"); } @@ -318,6 +320,8 @@ else if (strcmp("halt", p) == 0 || strcmp("reboot", p) == 0) exit(0); + else if (strcmp("switch", p) == 0) + cmd_switch(options); #ifndef NETBOOT else if (strcmp("ls", p) == 0) cmd_ls(options); Index: sys/arch/x68k/stand/netboot/Makefile =================================================================== RCS file: /cvsroot/src/sys/arch/x68k/stand/netboot/Makefile,v retrieving revision 1.3 diff -u -r1.3 Makefile --- sys/arch/x68k/stand/netboot/Makefile 6 Jul 2014 06:28:49 -0000 1.3 +++ sys/arch/x68k/stand/netboot/Makefile 1 Aug 2014 09:44:13 -0000 @@ -29,7 +29,7 @@ BOOTDIR= ${.CURDIR}/../boot .PATH: ${BOOTDIR} -SRCS= srt0.S boot.c conf.c exec_image.S if_ne.c ne.c dp8390.c +SRCS= srt0.S boot.c conf.c switch.c exec_image.S if_ne.c ne.c dp8390.c S= ${.CURDIR}/../../../.. M= ${.CURDIR}/../.. COMMONDIR= $M/stand/common --- /dev/null 2014-08-01 18:55:01.000000000 +0900 +++ sys/arch/x68k/stand/boot/switch.c 2014-08-01 18:59:49.000000000 +0900 @@ -0,0 +1,333 @@ +/* $NetBSD$ */ + +/* + * Copyright (c) 2014 Tetsuya Isaki. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <lib/libsa/stand.h> +#include <lib/libkern/libkern.h> + +#include "switch.h" + +#define SRAM_MEMSIZE (*((volatile uint32_t *)0x00ed0008)) +#define SRAM_ROMADDR (*((volatile uint32_t *)0x00ed000c)) +#define SRAM_RAMADDR (*((volatile uint32_t *)0x00ed0010)) +#define SRAM_BOOTDEV (*((volatile uint16_t *)0x00ed0018)) + +#define SYSPORT_SRAM_WP (*((volatile uint8_t *)0x00e8e00d)) + +static int hextoi(const char *); +static void cmd_switch_help(void); +static void cmd_switch_show(void); +static void cmd_switch_show_boot(void); +static void cmd_switch_show_rom(void); +static void cmd_switch_show_memory(void); +static const char *romaddr_tostr(uint32_t); +static const char *get_romaddr_name(uint32_t); +static void cmd_switch_boot(const char *); +static void cmd_switch_rom(const char *); +static void cmd_switch_memory(const char *); + +static inline void +sram_write_enable(void) +{ + SYSPORT_SRAM_WP = 0x31; +} + +static inline void +sram_write_disable(void) +{ + SYSPORT_SRAM_WP = 0; +} + +/* XXX atoi is dumb copy from i386/stand/lib/bootmenu.c ... */ +#define isnum(c) ((c) >= '0' && (c) <= '9') +static int +atoi(const char *in) +{ + char *c; + int ret; + + ret = 0; + c = (char *)in; + if (*c == '-') + c++; + for (; isnum(*c); c++) + ret = (ret * 10) + (*c - '0'); + + return (*in == '-') ? -ret : ret; +} + +#define isxdigit(c) (isnum(c) || (((c) | 0x20) >= 'a' && ((c) | 0x20) <= 'f')) +static int +hextoi(const char *in) +{ + char *c; + int ret; + + ret = 0; + c = (char *)in; + for (; isxdigit(*c); c++) { + ret = (ret * 16) + + (*c > '9' ? ((*c | 0x20) - 'a' + 10) : *c - '0'); + } + return ret; +} + +static void +cmd_switch_help(void) +{ + printf( + "usage: switch <key>=<val>\n" + " boot=[std | inscsi<N> | exscsi<N> | fd<N> | rom ]\n" + " rom=[ inscsi<N> | exscsi<N> | $<addr> ]\n" + " memory=<1..12> (unit:MB)\n" + " switch show\n" + ); +} + +void +cmd_switch(char *arg) +{ + char *val; + + if (strcmp(arg, "show") == 0) { + cmd_switch_show(); + return; + } + + val = strchr(arg, '='); + if (val == NULL) { + cmd_switch_help(); + return; + } + *val++ = '\0'; + + if (strcmp(arg, "boot") == 0) { + cmd_switch_boot(val); + } else if (strcmp(arg, "rom") == 0) { + cmd_switch_rom(val); + } else if (strcmp(arg, "memory") == 0) { + cmd_switch_memory(val); + } else { + cmd_switch_help(); + } +} + +static void +cmd_switch_show(void) +{ + cmd_switch_show_boot(); + cmd_switch_show_rom(); + cmd_switch_show_memory(); +} + +static void +cmd_switch_show_boot(void) +{ + uint32_t romaddr; + uint16_t bootdev; + const char *name; + + bootdev = SRAM_BOOTDEV; + romaddr = SRAM_ROMADDR; + + /* + * $0000: std + * $8n00: sasi<N> + * $9n70: fd<N> + * $a000: ROM + * $b000: RAM + */ + printf("boot="); + switch (bootdev >> 12) { + default: + case 0x0: + /* + * The real order is fd->sasi->rom->ram + * but it is a bit redundant.. + */ + printf("std (fd -> "); + name = get_romaddr_name(romaddr); + if (name) + printf("%s)", name); + else + printf("rom$%x)", romaddr); + break; + case 0x8: + printf("sasi%d", (bootdev >> 8) & 15); + break; + case 0x9: + printf("fd%d", (bootdev >> 8) & 3); + break; + case 0xa: + printf("rom%s", romaddr_tostr(romaddr)); + break; + case 0xb: + printf("ram$%x", SRAM_RAMADDR); + break; + } + printf("\n"); +} + +static void +cmd_switch_show_rom(void) +{ + uint32_t romaddr; + + romaddr = SRAM_ROMADDR; + printf("rom=%s\n", romaddr_tostr(romaddr)); +} + +static void +cmd_switch_show_memory(void) +{ + printf("memory=%d MB\n", SRAM_MEMSIZE / (1024 * 1024)); +} + +/* return rom address as string with name if any */ +static const char * +romaddr_tostr(uint32_t addr) +{ + static char buf[32]; + const char *name; + + name = get_romaddr_name(addr); + if (name) + snprintf(buf, sizeof(buf), "$%x (%s)", addr, name); + else + snprintf(buf, sizeof(buf), "$%x", addr); + + return buf; +} + +/* + * return "inscsiN" / "exscsiN" if addr is in range of SCSI boot. + * Otherwise return NULL. + */ +static const char * +get_romaddr_name(uint32_t addr) +{ + static char buf[8]; + + if (0xfc0000 <= addr && addr < 0xfc0020 && addr % 4 == 0) { + snprintf(buf, sizeof(buf), "inscsi%d", (addr >> 2) & 7); + } else if (0xea0020 <= addr && addr < 0xea0040 && addr % 4 == 0) { + snprintf(buf, sizeof(buf), "exscsi%d", (addr >> 2) & 7); + } else { + return NULL; + } + return buf; +} + +static void +cmd_switch_boot(const char *arg) +{ + int id; + uint32_t romaddr; + uint16_t bootdev; + + romaddr = 0xffffffff; + + if (strcmp(arg, "std") == 0) { + bootdev = 0x0000; + + } else if (strcmp(arg, "rom") == 0) { + bootdev = 0xa000; + + } else if (strncmp(arg, "inscsi", 6) == 0) { + id = (arg[6] - '0') & 7; + bootdev = 0xa000; + romaddr = 0xfc0000 + id * 4; + + } else if (strncmp(arg, "exscsi", 6) == 0) { + id = (arg[6] - '0') & 7; + bootdev = 0xa000; + romaddr = 0xea0020 + id * 4; + + } else if (strncmp(arg, "fd", 2) == 0) { + id = (arg[2] - '0') & 3; + bootdev = 0x9070 | (id << 8); + + } else { + cmd_switch_help(); + return; + } + + sram_write_enable(); + SRAM_BOOTDEV = bootdev; + if (romaddr != 0xffffffff) + SRAM_ROMADDR = romaddr; + sram_write_disable(); + + cmd_switch_show_boot(); +} + +static void +cmd_switch_rom(const char *arg) +{ + int id; + uint32_t romaddr; + + if (strncmp(arg, "inscsi", 6) == 0) { + id = (arg[6] - '0') & 7; + romaddr = 0xfc0000 + id * 4; + + } else if (strncmp(arg, "exscsi", 6) == 0) { + id = (arg[6] - '0') & 7; + romaddr = 0xea0020 + id * 4; + + } else if (*arg == '$') { + romaddr = hextoi(arg + 1); + + } else { + cmd_switch_help(); + return; + } + + sram_write_enable(); + SRAM_ROMADDR = romaddr; + sram_write_disable(); + + cmd_switch_show_rom(); +} + +static void +cmd_switch_memory(const char *arg) +{ + int num; + + num = atoi(arg); + if (num < 1 || num > 12) { + cmd_switch_help(); + return; + } + + sram_write_enable(); + SRAM_MEMSIZE = num * (1024 * 1024); + sram_write_disable(); + + cmd_switch_show_memory(); +} --- /dev/null 2014-08-01 18:55:01.000000000 +0900 +++ sys/arch/x68k/stand/boot/switch.h 2014-08-01 14:39:22.000000000 +0900 @@ -0,0 +1,28 @@ +/* $NetBSD$ */ + +/* + * Copyright (c) 2014 Tetsuya Isaki. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +extern void cmd_switch(char *);