Annotation of qemu/roms/openbios/arch/sparc32/romvec.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * PROM interface support
        !             3:  * Copyright 1996 The Australian National University.
        !             4:  * Copyright 1996 Fujitsu Laboratories Limited
        !             5:  * Copyright 1999 Pete A. Zaitcev
        !             6:  * This software may be distributed under the terms of the Gnu
        !             7:  * Public License version 2 or later
        !             8:  */
        !             9: 
        !            10: #include <stdarg.h>
        !            11: 
        !            12: #include "openprom.h"
        !            13: #include "config.h"
        !            14: #include "libopenbios/bindings.h"
        !            15: #include "drivers/drivers.h"
        !            16: #include "libopenbios/sys_info.h"
        !            17: #include "boot.h"
        !            18: #include "romvec.h"
        !            19: 
        !            20: #ifdef CONFIG_DEBUG_OBP
        !            21: #define DPRINTF(fmt, args...)                   \
        !            22:     do { printk(fmt , ##args); } while (0)
        !            23: #else
        !            24: #define DPRINTF(fmt, args...)
        !            25: #endif
        !            26: 
        !            27: char obp_stdin, obp_stdout;
        !            28: static int obp_fd_stdin, obp_fd_stdout;
        !            29: const char *obp_stdin_path, *obp_stdout_path;
        !            30: 
        !            31: struct linux_arguments_v0 obp_arg;
        !            32: const char *bootpath;
        !            33: static const struct linux_arguments_v0 * const obp_argp = &obp_arg;
        !            34: 
        !            35: static void (*sync_hook)(void);
        !            36: 
        !            37: static struct linux_romvec romvec0;
        !            38: 
        !            39: static void doublewalk(__attribute__((unused)) unsigned int ptab1,
        !            40:                        __attribute__((unused)) unsigned int va)
        !            41: {
        !            42: }
        !            43: 
        !            44: int obp_nextnode(int node)
        !            45: {
        !            46:     int peer;
        !            47: 
        !            48:     PUSH(node);
        !            49:     fword("peer");
        !            50:     peer = POP();
        !            51:     DPRINTF("obp_nextnode(0x%x) = 0x%x\n", node, peer);
        !            52: 
        !            53:     return peer;
        !            54: }
        !            55: 
        !            56: int obp_child(int node)
        !            57: {
        !            58:     int child;
        !            59: 
        !            60:     PUSH(node);
        !            61:     fword("child");
        !            62:     child = POP();
        !            63:     DPRINTF("obp_child(0x%x) = 0x%x\n", node, child);
        !            64: 
        !            65:     return child;
        !            66: }
        !            67: 
        !            68: int obp_proplen(int node, const char *name)
        !            69: {
        !            70:     int notfound;
        !            71: 
        !            72:     if (!node) {
        !            73:         DPRINTF("obp_proplen(0x0, %s) = -1\n", name);
        !            74:         return -1;
        !            75:     }
        !            76: 
        !            77:     push_str(name);
        !            78:     PUSH(node);
        !            79:     fword("get-package-property");
        !            80:     notfound = POP();
        !            81: 
        !            82:     if (notfound) {
        !            83:         DPRINTF("obp_proplen(0x%x, %s) (not found)\n", node, name);
        !            84: 
        !            85:         return -1;
        !            86:     } else {
        !            87:         int len;
        !            88: 
        !            89:         len = POP();
        !            90:         (void) POP();
        !            91:         DPRINTF("obp_proplen(0x%x, %s) = %d\n", node, name, len);
        !            92: 
        !            93:         return len;
        !            94:     }
        !            95: }
        !            96: 
        !            97: #ifdef CONFIG_DEBUG_OBP
        !            98: static int looks_like_string(const char *str, int len)
        !            99: {
        !           100:     int i;
        !           101:     int ret = (str[len-1] == '\0');
        !           102:     for (i = 0; i < len-1 && ret; i++)
        !           103:     {
        !           104:         int ch = str[i] & 0xFF;
        !           105:         if (ch < 0x20 || ch > 0x7F)
        !           106:             ret = 0;
        !           107:     }
        !           108:     return ret;
        !           109: }
        !           110: #endif
        !           111: 
        !           112: int obp_getprop(int node, const char *name, char *value)
        !           113: {
        !           114:     int notfound, found;
        !           115:     int len;
        !           116:     const char *str;
        !           117: 
        !           118:     if (!node) {
        !           119:         DPRINTF("obp_getprop(0x0, %s) = -1\n", name);
        !           120:         return -1;
        !           121:     }
        !           122: 
        !           123:     if (!name) {
        !           124:         // NULL name means get first property
        !           125:         push_str("");
        !           126:         PUSH(node);
        !           127:         fword("next-property");
        !           128:         found = POP();
        !           129:         if (found) {
        !           130:             len = POP();
        !           131:             str = (char *) POP();
        !           132:             DPRINTF("obp_getprop(0x%x, NULL) = %s\n", node, str);
        !           133: 
        !           134:             return (int)str;
        !           135:         }
        !           136:         DPRINTF("obp_getprop(0x%x, NULL) (not found)\n", node);
        !           137: 
        !           138:         return -1;
        !           139:     } else {
        !           140:         push_str(name);
        !           141:         PUSH(node);
        !           142:         fword("get-package-property");
        !           143:         notfound = POP();
        !           144:     }
        !           145:     if (notfound) {
        !           146:         DPRINTF("obp_getprop(0x%x, %s) (not found)\n", node, name);
        !           147: 
        !           148:         return -1;
        !           149:     } else {
        !           150:         len = POP();
        !           151:         str = (char *) POP();
        !           152:         if (len > 0)
        !           153:             memcpy(value, str, len);
        !           154:         else
        !           155:             str = "NULL";
        !           156: 
        !           157: #ifdef CONFIG_DEBUG_OBP
        !           158:         if (looks_like_string(str, len)) {
        !           159:             DPRINTF("obp_getprop(0x%x, %s) = %s\n", node, name, str);
        !           160:         } else {
        !           161:             int i;
        !           162:             DPRINTF("obp_getprop(0x%x, %s) = ", node, name);
        !           163:             for (i = 0; i < len; i++) {
        !           164:                 DPRINTF("%02x%s", str[i] & 0xFF,
        !           165:                         (len == 4 || i == len-1) ? "" : " ");
        !           166:             }
        !           167:             DPRINTF("\n");
        !           168:         }
        !           169: #endif
        !           170: 
        !           171:         return len;
        !           172:     }
        !           173: }
        !           174: 
        !           175: const char *obp_nextprop(int node, const char *name)
        !           176: {
        !           177:     int found;
        !           178: 
        !           179:     if (!name || *name == '\0') {
        !           180:         // NULL name means get first property
        !           181:         push_str("");
        !           182:         name = "NULL";
        !           183:     } else {
        !           184:         push_str(name);
        !           185:     }
        !           186:     PUSH(node);
        !           187:     fword("next-property");
        !           188:     found = POP();
        !           189:     if (!found) {
        !           190:         DPRINTF("obp_nextprop(0x%x, %s) (not found)\n", node, name);
        !           191: 
        !           192:         return "";
        !           193:     } else {
        !           194:         char *str;
        !           195: 
        !           196:         POP(); /* len */
        !           197:         str = (char *) POP();
        !           198: 
        !           199:         DPRINTF("obp_nextprop(0x%x, %s) = %s\n", node, name, str);
        !           200: 
        !           201:         return str;
        !           202:     }
        !           203: }
        !           204: 
        !           205: int obp_setprop(__attribute__((unused)) int node,
        !           206:                        __attribute__((unused)) const char *name,
        !           207:                       __attribute__((unused)) char *value,
        !           208:                       __attribute__((unused)) int len)
        !           209: {
        !           210:     DPRINTF("obp_setprop(0x%x, %s) = %s (%d)\n", node, name, value, len);
        !           211: 
        !           212:     return -1;
        !           213: }
        !           214: 
        !           215: static const struct linux_nodeops nodeops0 = {
        !           216:     obp_nextnode_handler,      /* int (*no_nextnode)(int node); */
        !           217:     obp_child_handler,         /* int (*no_child)(int node); */
        !           218:     obp_proplen_handler,       /* int (*no_proplen)(int node, char *name); */
        !           219:     obp_getprop_handler,       /* int (*no_getprop)(int node,char *name,char *val); */
        !           220:     obp_setprop_handler,       /* int (*no_setprop)(int node, char *name,
        !           221:                                char *val, int len); */
        !           222:     obp_nextprop_handler       /* char * (*no_nextprop)(int node, char *name); */
        !           223: };
        !           224: 
        !           225: int obp_nbgetchar(void)
        !           226: {
        !           227:     return getchar();
        !           228: }
        !           229: 
        !           230: int obp_nbputchar(int ch)
        !           231: {
        !           232:     putchar(ch);
        !           233: 
        !           234:     return 0;
        !           235: }
        !           236: 
        !           237: void obp_putstr(char *str, int len)
        !           238: {
        !           239:     PUSH(pointer2cell(str));
        !           240:     PUSH(len);
        !           241:     fword("type");
        !           242: }
        !           243: 
        !           244: void obp_printf(const char *fmt, ...)
        !           245: {
        !           246:     va_list ap;
        !           247: 
        !           248:     va_start(ap, fmt);
        !           249:     printk(fmt, ap);
        !           250:     va_end(ap);
        !           251: }
        !           252: 
        !           253: void obp_reboot(char *str)
        !           254: {
        !           255:     printk("rebooting (%s)\n", str);
        !           256:     *reset_reg = 1;
        !           257:     printk("reboot failed\n");
        !           258:     for (;;) {}
        !           259: }
        !           260: 
        !           261: void obp_abort(void)
        !           262: {
        !           263:     printk("abort, power off\n");
        !           264:     *power_reg = 1;
        !           265:     printk("power off failed\n");
        !           266:     for (;;) {}
        !           267: }
        !           268: 
        !           269: void obp_halt(void)
        !           270: {
        !           271:     printk("halt, power off\n");
        !           272:     *power_reg = 1;
        !           273:     printk("power off failed\n");
        !           274:     for (;;) {}
        !           275: }
        !           276: 
        !           277: int obp_devopen(char *str)
        !           278: {
        !           279:     int ret;
        !           280: 
        !           281:     push_str(str);
        !           282:     fword("open-dev");
        !           283:     ret = POP();
        !           284:     DPRINTF("obp_devopen(%s) = 0x%x\n", str, ret);
        !           285: 
        !           286:     return ret;
        !           287: }
        !           288: 
        !           289: int obp_devclose(int dev_desc)
        !           290: {
        !           291:     int ret = 1;
        !           292: 
        !           293:     PUSH(dev_desc);
        !           294:     fword("close-dev");
        !           295: 
        !           296:     DPRINTF("obp_devclose(0x%x) = %d\n", dev_desc, ret);
        !           297: 
        !           298:     return ret;
        !           299: }
        !           300: 
        !           301: int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf)
        !           302: {
        !           303:     int ret, hi, lo, bs;
        !           304: 
        !           305:     bs = 512;
        !           306:     hi = ((uint64_t)offset * bs) >> 32;
        !           307:     lo = ((uint64_t)offset * bs) & 0xffffffff;
        !           308: 
        !           309:     ret = obp_devseek(dev_desc, hi, lo);
        !           310: 
        !           311:     ret = obp_devread(dev_desc, buf, num_blks * bs) / bs;
        !           312: 
        !           313:     DPRINTF("obp_rdblkdev(fd 0x%x, num_blks %d, offset %d (hi %d lo %d), buf 0x%x) = %d\n", dev_desc, num_blks, offset, hi, lo, (int)buf, ret);
        !           314: 
        !           315:     return ret;
        !           316: }
        !           317: 
        !           318: int obp_devread(int dev_desc, char *buf, int nbytes)
        !           319: {
        !           320:     int ret;
        !           321: 
        !           322:     PUSH((int)buf);
        !           323:     PUSH(nbytes);
        !           324:     push_str("read");
        !           325:     PUSH(dev_desc);
        !           326:     fword("$call-method");
        !           327:     ret = POP();
        !           328: 
        !           329:     DPRINTF("obp_devread(fd 0x%x, buf 0x%x, nbytes %d) = %d\n", dev_desc, (int)buf, nbytes, ret);
        !           330: 
        !           331:     return ret;
        !           332: }
        !           333: 
        !           334: int obp_devwrite(int dev_desc, char *buf, int nbytes)
        !           335: {
        !           336: #ifdef CONFIG_DEBUG_OBP_DEVWRITE /* disabled, makes too much noise */
        !           337:     int ret;
        !           338: #endif
        !           339: 
        !           340:     PUSH((int)buf);
        !           341:     PUSH(nbytes);
        !           342:     push_str("write");
        !           343:     PUSH(dev_desc);
        !           344:     fword("$call-method");
        !           345: #ifdef CONFIG_DEBUG_OBP_DEVWRITE
        !           346:     ret = POP();
        !           347:     DPRINTF("obp_devwrite(fd 0x%x, buf %s, nbytes %d) = %d\n", dev_desc, buf, nbytes, ret);
        !           348: #else
        !           349:     POP();
        !           350: #endif
        !           351: 
        !           352:     return nbytes;
        !           353: }
        !           354: 
        !           355: int obp_devseek(int dev_desc, int hi, int lo)
        !           356: {
        !           357:     int ret;
        !           358: 
        !           359:     PUSH(lo);
        !           360:     PUSH(hi);
        !           361:     push_str("seek");
        !           362:     PUSH(dev_desc);
        !           363:     fword("$call-method");
        !           364:     ret = POP();
        !           365: 
        !           366:     DPRINTF("obp_devseek(fd 0x%x, hi %d, lo %d) = %d\n", dev_desc, hi, lo, ret);
        !           367: 
        !           368:     return ret;
        !           369: }
        !           370: 
        !           371: int obp_inst2pkg(int dev_desc)
        !           372: {
        !           373:     int ret;
        !           374: 
        !           375:     PUSH(dev_desc);
        !           376:     fword("ihandle>non-interposed-phandle");
        !           377:     ret = POP();
        !           378: 
        !           379:     DPRINTF("obp_inst2pkg(fd 0x%x) = 0x%x\n", dev_desc, ret);
        !           380: 
        !           381:     return ret;
        !           382: }
        !           383: 
        !           384: int obp_cpustart(__attribute__((unused))unsigned int whichcpu,
        !           385:                         __attribute__((unused))int ctxtbl_ptr,
        !           386:                         __attribute__((unused))int thiscontext,
        !           387:                         __attribute__((unused))char *prog_counter)
        !           388: {
        !           389:     int cpu, found;
        !           390:     struct linux_prom_registers *smp_ctable = (void *)ctxtbl_ptr;
        !           391: 
        !           392:     DPRINTF("obp_cpustart: cpu %d, ctxptr 0x%x, ctx %d, pc 0x%x\n", whichcpu,
        !           393:             smp_ctable->phys_addr, thiscontext, (unsigned int)prog_counter);
        !           394: 
        !           395:     found = obp_getprop(whichcpu, "mid", (char *)&cpu);
        !           396:     if (found == -1)
        !           397:         return -1;
        !           398:     DPRINTF("cpu found, id %d -> cpu %d\n", whichcpu, cpu);
        !           399: 
        !           400:     return start_cpu((unsigned int)prog_counter, ((unsigned int)smp_ctable->phys_addr) >> 4,
        !           401:               thiscontext, cpu);
        !           402: }
        !           403: 
        !           404: int obp_cpustop(__attribute__((unused)) unsigned int whichcpu)
        !           405: {
        !           406:     DPRINTF("obp_cpustop: cpu %d\n", whichcpu);
        !           407: 
        !           408:     return 0;
        !           409: }
        !           410: 
        !           411: int obp_cpuidle(__attribute__((unused)) unsigned int whichcpu)
        !           412: {
        !           413:     DPRINTF("obp_cpuidle: cpu %d\n", whichcpu);
        !           414: 
        !           415:     return 0;
        !           416: }
        !           417: 
        !           418: int obp_cpuresume(__attribute__((unused)) unsigned int whichcpu)
        !           419: {
        !           420:     DPRINTF("obp_cpuresume: cpu %d\n", whichcpu);
        !           421: 
        !           422:     return 0;
        !           423: }
        !           424: 
        !           425: void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, int arg3, int arg4)
        !           426: {
        !           427:   int dstacktmp = 0;
        !           428: 
        !           429:   // It seems Solaris passes up to 5 arguments which should be pushed onto the Forth
        !           430:   // stack for execution. However the API doesn't provide for a way to specify the number
        !           431:   // of arguments actually being passed. Hence we preserve the state of the Forth stack 
        !           432:   // before, push all the arguments, execute the Forth, then restore the stack to its 
        !           433:   // previous state. This enables us to have a variable number of arguments and still 
        !           434:   // preserve stack state between subsequent calls.
        !           435: 
        !           436:   // Preserve stack state
        !           437:   dstacktmp = dstackcnt;
        !           438: 
        !           439:   PUSH(arg4);
        !           440:   PUSH(arg3);
        !           441:   PUSH(arg2);
        !           442:   PUSH(arg1);
        !           443:   PUSH(arg0);
        !           444: 
        !           445:   DPRINTF("obp_fortheval_v2(%x %x %x %x %x %s)\n", arg4, arg3, arg2, arg1, arg0, str);
        !           446:   push_str(str);
        !           447:   fword("eval");
        !           448: 
        !           449:   // Restore stack state
        !           450:   dstackcnt = dstacktmp;
        !           451: }
        !           452: 
        !           453: void *
        !           454: init_openprom(void)
        !           455: {
        !           456:     /* Setup the openprom vector. Note that all functions should be invoked
        !           457:        via their handler (see call-romvec.S) which acts as a proxy to save
        !           458:        the globals and setup the stack correctly */
        !           459: 
        !           460:     // Linux wants a R/W romvec table
        !           461:     romvec0.pv_magic_cookie = LINUX_OPPROM_MAGIC;
        !           462:     romvec0.pv_romvers = 3;
        !           463:     romvec0.pv_plugin_revision = 2;
        !           464:     romvec0.pv_printrev = 0x20019;
        !           465:     romvec0.pv_v0mem.v0_totphys = &ptphys;
        !           466:     romvec0.pv_v0mem.v0_prommap = &ptmap;
        !           467:     romvec0.pv_v0mem.v0_available = &ptavail;
        !           468:     romvec0.pv_nodeops = &nodeops0;
        !           469:     romvec0.pv_bootstr = (void *)doublewalk;
        !           470:     romvec0.pv_v0devops.v0_devopen = &obp_devopen_handler;
        !           471:     romvec0.pv_v0devops.v0_devclose = &obp_devclose_handler;
        !           472:     romvec0.pv_v0devops.v0_rdblkdev = &obp_rdblkdev_handler;
        !           473:     romvec0.pv_stdin = &obp_stdin;
        !           474:     romvec0.pv_stdout = &obp_stdout;
        !           475:     romvec0.pv_getchar = obp_nbgetchar_handler;
        !           476:     romvec0.pv_putchar = (void (*)(int))obp_nbputchar_handler;
        !           477:     romvec0.pv_nbgetchar = obp_nbgetchar_handler;
        !           478:     romvec0.pv_nbputchar = obp_nbputchar_handler;
        !           479:     romvec0.pv_putstr = obp_putstr_handler;
        !           480:     romvec0.pv_reboot = obp_reboot_handler;
        !           481:     romvec0.pv_printf = obp_printf_handler;
        !           482:     romvec0.pv_abort = obp_abort_handler;
        !           483:     romvec0.pv_halt = obp_halt_handler;
        !           484:     romvec0.pv_synchook = &sync_hook;
        !           485:     romvec0.pv_v0bootargs = &obp_argp;
        !           486:     romvec0.pv_fortheval.v2_eval = obp_fortheval_v2_handler;
        !           487:     romvec0.pv_v2devops.v2_inst2pkg = obp_inst2pkg_handler;
        !           488:     romvec0.pv_v2devops.v2_dumb_mem_alloc = obp_dumb_memalloc_handler;
        !           489:     romvec0.pv_v2devops.v2_dumb_mem_free = obp_dumb_memfree_handler;
        !           490:     romvec0.pv_v2devops.v2_dumb_mmap = obp_dumb_mmap_handler;
        !           491:     romvec0.pv_v2devops.v2_dumb_munmap = obp_dumb_munmap_handler;
        !           492:     romvec0.pv_v2devops.v2_dev_open = obp_devopen_handler;
        !           493:     romvec0.pv_v2devops.v2_dev_close = (void (*)(int))obp_devclose_handler;
        !           494:     romvec0.pv_v2devops.v2_dev_read = obp_devread_handler;
        !           495:     romvec0.pv_v2devops.v2_dev_write = obp_devwrite_handler;
        !           496:     romvec0.pv_v2devops.v2_dev_seek = obp_devseek_handler;
        !           497: 
        !           498:     romvec0.pv_v2bootargs.bootpath = &bootpath;
        !           499: 
        !           500:     romvec0.pv_v2bootargs.bootargs = &obp_arg.argv[1];
        !           501:     romvec0.pv_v2bootargs.fd_stdin = &obp_fd_stdin;
        !           502:     romvec0.pv_v2bootargs.fd_stdout = &obp_fd_stdout;
        !           503: 
        !           504:     push_str(obp_stdin_path);
        !           505:     fword("open-dev");
        !           506:     obp_fd_stdin = POP();
        !           507:     push_str(obp_stdout_path);
        !           508:     fword("open-dev");
        !           509:     obp_fd_stdout = POP();
        !           510: 
        !           511:     romvec0.v3_memalloc = obp_memalloc_handler;
        !           512: 
        !           513:     romvec0.v3_cpustart = obp_cpustart_handler;
        !           514:     romvec0.v3_cpustop = obp_cpustop_handler;
        !           515:     romvec0.v3_cpuidle = obp_cpuidle_handler;
        !           516:     romvec0.v3_cpuresume = obp_cpuresume_handler;
        !           517: 
        !           518:     return &romvec0;
        !           519: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.