Annotation of qemu/roms/openbios/arch/ppc/mol/main.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *   Creation Date: <2002/10/02 22:24:24 samuel>
        !             3:  *   Time-stamp: <2004/03/27 01:57:55 samuel>
        !             4:  *
        !             5:  *     <main.c>
        !             6:  *
        !             7:  *
        !             8:  *
        !             9:  *   Copyright (C) 2002, 2003, 2004 Samuel Rydh ([email protected])
        !            10:  *
        !            11:  *   This program is free software; you can redistribute it and/or
        !            12:  *   modify it under the terms of the GNU General Public License
        !            13:  *   as published by the Free Software Foundation
        !            14:  *
        !            15:  */
        !            16: 
        !            17: 
        !            18: #include "config.h"
        !            19: #include "libopenbios/bindings.h"
        !            20: #include "libopenbios/elfload.h"
        !            21: #include "arch/common/nvram.h"
        !            22: #include "libc/diskio.h"
        !            23: #include "libc/vsprintf.h"
        !            24: #include "mol/mol.h"
        !            25: #include "libopenbios/ofmem.h"
        !            26: #include "osi_calls.h"
        !            27: #include "ablk_sh.h"
        !            28: #include "boothelper_sh.h"
        !            29: 
        !            30: 
        !            31: static void    patch_newworld_rom( char *start, size_t size );
        !            32: static void    newworld_timer_hack( char *start, size_t size );
        !            33: 
        !            34: static void
        !            35: transfer_control_to_elf( unsigned long entry )
        !            36: {
        !            37:        extern void call_elf( unsigned long entry );
        !            38:        printk("Starting ELF boot loader\n");
        !            39:        call_elf( entry );
        !            40: 
        !            41:        fatal_error("call_elf returned unexpectedly\n");
        !            42: }
        !            43: 
        !            44: static int
        !            45: load_elf_rom( unsigned long *entry, int fd )
        !            46: {
        !            47:        int i, lszz_offs, elf_offs;
        !            48:        char buf[128], *addr;
        !            49:        Elf_ehdr ehdr;
        !            50:        Elf_phdr *phdr;
        !            51:        size_t s;
        !            52: 
        !            53:        printk("Loading '%s' from '%s'\n", get_file_path(fd),
        !            54:               get_volume_name(fd) );
        !            55: 
        !            56:        /* the ELF-image (usually) starts at offset 0x4000 */
        !            57:        if( (elf_offs=find_elf(fd)) < 0 ) {
        !            58:                printk("----> %s is not an ELF image\n", buf );
        !            59:                exit(1);
        !            60:        }
        !            61:        if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) )
        !            62:                fatal_error("elf_readhdrs failed\n");
        !            63: 
        !            64:        *entry = ehdr.e_entry;
        !            65: 
        !            66:        /* load segments. Compressed ROM-image assumed to be located immediately
        !            67:         * after the last segment */
        !            68:        lszz_offs = elf_offs;
        !            69:        for( i=0; i<ehdr.e_phnum; i++ ) {
        !            70:                /* p_memsz, p_flags */
        !            71:                s = MIN( phdr[i].p_filesz, phdr[i].p_memsz );
        !            72:                seek_io( fd, elf_offs + phdr[i].p_offset );
        !            73: 
        !            74:                /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n",
        !            75:                   phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset,
        !            76:                   phdr[i].p_vaddr ); */
        !            77: 
        !            78:                if( phdr[i].p_vaddr != phdr[i].p_paddr )
        !            79:                        printk("WARNING: ELF segment virtual addr != physical addr\n");
        !            80:                lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz );
        !            81:                if( !s )
        !            82:                        continue;
        !            83:                if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 )
        !            84:                        fatal_error("Claim failed!\n");
        !            85: 
        !            86:                addr = (char*)phdr[i].p_vaddr;
        !            87:                if( read_io(fd, addr, s) != s )
        !            88:                        fatal_error("read failed\n");
        !            89: 
        !            90:                /* patch CODE segment */
        !            91:                if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) {
        !            92:                        patch_newworld_rom( (char*)phdr[i].p_vaddr, s );
        !            93:                        newworld_timer_hack( (char*)phdr[i].p_vaddr, s );
        !            94:                }
        !            95:                flush_icache_range( addr, addr+s );
        !            96: 
        !            97:                /* printk("ELF ROM-section loaded at %08lX (size %08lX)\n",
        !            98:                   (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/
        !            99:        }
        !           100:        free( phdr );
        !           101:        return lszz_offs;
        !           102: }
        !           103: 
        !           104: 
        !           105: /************************************************************************/
        !           106: /*     newworld ROM loading                                            */
        !           107: /************************************************************************/
        !           108: 
        !           109: #define ROM_BASE       0x1100000               /* where we decide to put things */
        !           110: 
        !           111: /* fix bug present in the 2.4 and the 3.0 Apple ROM */
        !           112: static void
        !           113: patch_newworld_rom( char *start, size_t size )
        !           114: {
        !           115:        int s;
        !           116:        unsigned long mark[] = { 0x7c7d1b78,            /* mr r29,r3 */
        !           117:                                  0x7c9c2378,           /* mr r28,r4 */
        !           118:                                  0x7cc33378,           /* mr r3,r6 */
        !           119:                                  0x7c864214,           /* add r4,r6,r8   <------ BUG -- */
        !           120:                                  0x80b10000,           /* lwz r5,0(r17) */
        !           121:                                  0x38a500e8 };         /* addi r5,r5,232 */
        !           122: 
        !           123:        /* Correcting add r4,r6,r8  ---->  addi r4,r6,8 */
        !           124:        for( s=0; s<size-sizeof(mark); s+=4 )
        !           125:                if( memcmp( start+s, mark, sizeof(mark)) == 0 ) {
        !           126:                        printk("FIXING ROM BUG @ %X!\n", s+12);
        !           127:                        ((unsigned long*)(start+s))[3] = 0x38860008;    /* addi r4,r6,8 */
        !           128:                }
        !           129: }
        !           130: 
        !           131: /* This hack is only needed on machines with a timebase slower than 12.5 MHz
        !           132:  * (50 MHz bus frequency). Typically only old, accelerated machines fall
        !           133:  * into this category. The cause of the problem is an overflow in Apple's
        !           134:  * calibration routine.
        !           135:  */
        !           136: static void
        !           137: newworld_timer_hack( char *start, size_t size )
        !           138: {
        !           139:        int s;
        !           140:        unsigned long mark[] = { 0x7d0000a6, 0x5507045e, 0x7ce00124, 0x4c00012c,
        !           141:                                  0x38e00000, 0x3c80000f, 0x6084ffff, 0x98830c00,
        !           142:                                  0x7c0006ac, 0x98830a00, 0x7c0006ac, 0x7c9603a6,
        !           143:                                  0x4c00012c, 0x7cb602a6, 0x2c050000, 0x4181fff8,
        !           144:                                  0x7c0004ac, 0x88830a00, 0x7c0006ac, 0x88a30800,
        !           145:                                  0x7c0006ac, 0x88c30a00, 0x7c0006ac, 0x7c043040,
        !           146:                                  0x40a2ffe4, 0x5085442e, 0x7ca500d0, 0x54a5043e,
        !           147:                                  0x7c053840, 0x7ca72b78, 0x4082ff9c, 0x7ca32b78,
        !           148:                                  0x7d000124, 0x4c00012c, 0x4e800020
        !           149:        };
        !           150: 
        !           151:        /* return #via ticks corresponding to 0xfffff DEC ticks (VIA frequency == 47/60 MHz) */
        !           152:        for( s=0; s < size-sizeof(mark); s+=4 ) {
        !           153:                if( !memcmp( start+s, mark, sizeof(mark)) ) {
        !           154:                        extern char timer_calib_start[], timer_calib_end[];
        !           155:                        extern unsigned long nw_dec_calibration;
        !           156:                        int hz = OSI_UsecsToMticks(1000);
        !           157:                        nw_dec_calibration = OSI_MticksToUsecs(0xfffff*47)/60;
        !           158:                        memcpy( start + s, timer_calib_start, timer_calib_end - timer_calib_start );
        !           159: 
        !           160:                        printk("Timer calibration fix: %d.%02d MHz [%ld]\n",
        !           161:                               hz/1000, (hz/10)%100, nw_dec_calibration );
        !           162:                        break;
        !           163:                }
        !           164:        }
        !           165: }
        !           166: 
        !           167: static unsigned long
        !           168: load_newworld_rom( int fd )
        !           169: {
        !           170:        int lszz_offs, lszz_size;
        !           171:        unsigned long entry, data[2];
        !           172:        phandle_t ph;
        !           173: 
        !           174:        lszz_offs = load_elf_rom( &entry, fd );
        !           175:        seek_io( fd, -1 );
        !           176:        lszz_size = tell(fd) - lszz_offs;
        !           177:        seek_io( fd, lszz_offs );
        !           178: 
        !           179:        /* printk("Compressed ROM image: offset %08X, size %08X loaded at %08x\n",
        !           180:           lszz_offs, lszz_size, ROM_BASE ); */
        !           181: 
        !           182:        if( ofmem_claim(ROM_BASE, lszz_size, 0) == -1 )
        !           183:                fatal_error("Claim failure (lszz)!\n");
        !           184: 
        !           185:        read_io( fd, (char*)ROM_BASE, lszz_size );
        !           186: 
        !           187:        /* Fix the /rom/macos/AAPL,toolbox-image,lzss property (phys, size) */
        !           188: #if 0
        !           189:        if( (ph=prom_create_node("/rom/macos/")) == -1 )
        !           190:                fatal_error("Failed creating /rom/macos/");
        !           191: #else
        !           192:        ph = find_dev("/rom/macos");
        !           193: #endif
        !           194:        data[0] = ROM_BASE;
        !           195:        data[1] = lszz_size;
        !           196:        set_property( ph, "AAPL,toolbox-image,lzss", (char*)data, sizeof(data) );
        !           197: 
        !           198:        /* The 7.8 rom (MacOS 9.2) uses AAPL,toolbox-parcels instead of
        !           199:         * AAPL,toolbox-image,lzss. It probably doesn't hurt to have it
        !           200:         * always present (we don't have an easy way to determine ROM version...)
        !           201:         */
        !           202:        set_property( ph, "AAPL,toolbox-parcels", (char*)data, sizeof(data) );
        !           203:        return entry;
        !           204: }
        !           205: 
        !           206: static int
        !           207: search_nwrom( int fd, int fast )
        !           208: {
        !           209:        char *s, buf[128];
        !           210:        int found = 0;
        !           211: 
        !           212:        if( fast ) {
        !           213:                int ind;
        !           214:                found = !reopen( fd, "\\\\:tbxi" );
        !           215:                for( ind=0; !found && (s=BootHGetStrResInd("macos_rompath", buf, sizeof(buf), ind++, 0)) ; )
        !           216:                        found = !reopen( fd, s );
        !           217:                for( ind=0; !found && (s=BootHGetStrResInd("macos_rompath_", buf, sizeof(buf), ind++, 0)) ; )
        !           218:                        found = !reopen( fd, s );
        !           219:        } else {
        !           220:                printk("Searching %s for a 'Mac OS ROM' file\n", get_volume_name(fd) );
        !           221:                if( !(found=reopen_nwrom(fd)) ) {
        !           222:                        printk(" \n**** HINT ***************************************************\n");
        !           223:                        printk("*  The booting can be speeded up by adding the line\n");
        !           224:                        printk("*      macos_rompath: '%s'\n", get_file_path(fd) );
        !           225:                        printk("*  to the /etc/mol/molrc.macos (recommended).\n");
        !           226:                        printk("*************************************************************\n \n");
        !           227:                }
        !           228:        }
        !           229:        return found;
        !           230: }
        !           231: 
        !           232: static void
        !           233: encode_bootpath( const char *spec, const char *args )
        !           234: {
        !           235:        phandle_t chosen_ph = find_dev("/chosen");
        !           236:        set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 );
        !           237:        set_property( chosen_ph, "bootargs", args, strlen(args)+1 );
        !           238: }
        !           239: 
        !           240: static char *
        !           241: newworld_load( const char *node_path, const char *spec, int do_search )
        !           242: {
        !           243:        char *p, *entry, buf[80];
        !           244:        int fd, len;
        !           245: 
        !           246:        if( (fd=open_io(spec)) == -1 )
        !           247:                return NULL;
        !           248: 
        !           249:        if( !search_nwrom(fd, do_search) ) {
        !           250:                close_io(fd);
        !           251:                return NULL;
        !           252:        }
        !           253:        printk("Boot Disk: %s [%s]\n", spec, get_fstype(fd) );
        !           254: 
        !           255:        entry = (char*)load_newworld_rom( fd );
        !           256: 
        !           257: #if 1
        !           258:        PUSH_ih( get_ih_from_fd(fd) );
        !           259:        fword("get-instance-path");
        !           260:        len = POP();
        !           261:        p = (char*)POP();
        !           262:        buf[0] = 0;
        !           263:        if( len < sizeof(buf) ) {
        !           264:                memcpy( buf, p, len );
        !           265:                buf[len] =0;
        !           266:        }
        !           267:        strcat( buf, "/x@:" );
        !           268:        printk("boot_path: %s\n", buf );
        !           269:        encode_bootpath( buf, "" );
        !           270: #endif
        !           271:        close_io( fd );
        !           272:        return entry;
        !           273: }
        !           274: 
        !           275: static void
        !           276: newworld_startup( void )
        !           277: {
        !           278:        int i, j, bootunit, type, fd;
        !           279:        ablk_disk_info_t info;
        !           280:        char *entry = NULL;
        !           281:        char spec[80];
        !           282:        phandle_t ph;
        !           283: 
        !           284:        char path[]="/pci/pci-bridge/mol-blk";
        !           285:        if( !(ph=find_dev(path)) )
        !           286:                fatal_error("MOLBlockDriver node not found\n");
        !           287: 
        !           288:        /* user-specified newworld ROMs take precedence */
        !           289:        if( (fd=open_io("pseudo:,nwrom")) >= 0 ) {
        !           290:                entry = (char*)load_newworld_rom( fd );
        !           291:                close_io( fd );
        !           292:        }
        !           293: 
        !           294:        /* determine boot volume */
        !           295:        for( bootunit=-1, type=0; bootunit==-1 && type<3 ; type++ ) {
        !           296:                for( i=0; !OSI_ABlkDiskInfo(0, i, &info) ; i++ ) {
        !           297:                        if( type<=1 && !(info.flags & ABLK_BOOT_HINT) )
        !           298:                                continue;
        !           299:                        if( type>1 && (info.flags & ABLK_BOOT_HINT) )
        !           300:                                continue;
        !           301: 
        !           302:                        for( j=0; !entry && j<32; j++ ) {
        !           303:                                 snprintf( spec, sizeof(spec), "%s/disk@%x:%d",
        !           304:                                           path, i, j );
        !           305:                                entry = newworld_load( path, spec, (!type || type==2) );
        !           306:                        }
        !           307:                        if( entry ) {
        !           308:                                bootunit = i;
        !           309:                                break;
        !           310:                        }
        !           311:                }
        !           312:        }
        !           313: 
        !           314:        if( entry ) {
        !           315:                OSI_ABlkBlessDisk( 0 /*channel*/, bootunit );
        !           316: 
        !           317:                update_nvram();
        !           318:                transfer_control_to_elf( (unsigned long)entry );
        !           319:                /* won't come here */
        !           320:                return;
        !           321:        }
        !           322: 
        !           323:        printk("\n--- No bootable disk was found! -----------------------------\n");
        !           324:        printk("If this is an oldworld machine, try booting from the MacOS\n");
        !           325:        printk("install CD and install MacOS from within MOL.\n");
        !           326:        printk("-------------------------------------------------------------\n");
        !           327:        exit(1);
        !           328: }
        !           329: 
        !           330: 
        !           331: /************************************************************************/
        !           332: /*     yaboot booting                                                  */
        !           333: /************************************************************************/
        !           334: 
        !           335: static void
        !           336: yaboot_startup( void )
        !           337: {
        !           338:        const char *paths[] = { "pseudo:,ofclient", "pseudo:,yaboot", NULL };
        !           339:        unsigned long entry;
        !           340:        int i, fd;
        !           341: 
        !           342:        for( i=0; paths[i]; i++ ) {
        !           343:                if( (fd=open_io(paths[i])) == -1 )
        !           344:                        continue;
        !           345:                (void) load_elf_rom( &entry, fd );
        !           346:                close_io( fd );
        !           347:                encode_bootpath( paths[i], "" );
        !           348: 
        !           349:                update_nvram();
        !           350:                transfer_control_to_elf( entry );
        !           351:                /* won't come here */
        !           352:        }
        !           353:        printk("*** Boot failure! No secondary bootloader specified ***\n");
        !           354:        exit(1);
        !           355: }
        !           356: 
        !           357: 
        !           358: /************************************************************************/
        !           359: /*     entry                                                           */
        !           360: /************************************************************************/
        !           361: 
        !           362: void
        !           363: boot( void )
        !           364: {
        !           365:        fword("update-chosen");
        !           366:        if( find_dev("/mol-platform") )
        !           367:                yaboot_startup();
        !           368:        else
        !           369:                newworld_startup();
        !           370: }

unix.superglobalmegacorp.com

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