root/sys/arch/atari/stand/bootxx/bootxx.c
/*      $NetBSD: bootxx.c,v 1.18 2025/11/19 09:43:27 nia Exp $  */

/*
 * Copyright (c) 1995 Waldi Ravens.
 * 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.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * 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.
 */

#define boot_BSD        bsd_startup

#include <lib/libsa/stand.h>
#include <atari_stand.h>
#include <libkern.h>
#include <tosdefs.h>
#include <sys/boot_flag.h>
#include <sys/exec.h>
#include <sys/reboot.h>
#include <machine/cpu.h>

typedef int      (*bxxx_t)(void *, void *, struct osdsc *);

int     bootxx(void *, void *, int);
void    boot_BSD(struct kparamb *) __attribute__((noreturn));
int     bootxxx(void *, void *, struct osdsc *);
int     load_booter(struct osdsc *);
int     usr_info(struct osdsc *);

#define BOOTXXX_MAXSIZE (64 * 1024)
#define HEAPSIZE        (64 * 1024)     /* should be >32KB for ffs blocksize */
#define HEAPSTART       (LOADADDR3 + BOOTXXX_MAXSIZE)
#define HEAPEND         (HEAPSTART + HEAPSIZE)

int
bootxx(void *readsector, void *disklabel, int autoboot)
{
        static osdsc_t  os_desc;
        extern char     end[], edata[];
        osdsc_t         *od = &os_desc;
        bxxx_t          bootxxx = (bxxx_t)(LOADADDR3);

        memset(edata, 0, end - edata);
        setheap((void *)HEAPSTART, (void *)HEAPEND);

        printf("\033v\nNetBSD/atari secondary bootloader"
                                                " ($Revision: 1.18 $)\n\n");

        if (init_dskio(readsector, disklabel, -1))
                return -1;

        for (;;) {
                od->rootfs = 0;                 /* partition a */
                od->osname = "/netbsd";
                od->ostype = &od->osname[1];
                od->boothowto = (RB_RDONLY);

                if (!autoboot) {
                        int     pref;

                        od->boothowto = (RB_RDONLY|RB_SINGLE);
                        pref = usr_info(od);
                        if (pref < 0)
                                continue;
                        if (pref > 0)
                                return pref;
                }
                autoboot = 0;                   /* in case auto boot fails */

                if (init_dskio(readsector, disklabel, od->rootfs))
                        continue;

                if (load_booter(od))
                        continue;

                (*bootxxx)(readsector, disklabel, od);
        }
        /* NOTREACHED */
}


int
usr_info(osdsc_t *od)
{
        static char     line[800];
        char            c, *p = line;

        printf("\nEnter os-type [.%s] root-fs [:a] kernel [%s]"
               " options [none]:\n\033e", od->ostype, od->osname);
        kgets(p, sizeof(line));
        printf("\033f");

        for (;;) {
                while (isspace(*p))
                        *p++ = '\0';

                switch (*p++) {
                case '\0':
                        goto done;
                case ':':
                        if ((c = *p) >= 'a' && c <= 'z')
                                od->rootfs = c - 'a';
                        else if (c >= 'A' && c <= 'Z')
                                od->rootfs = c - ('A' - 27);
                        else
                                return -1;

                        if (!od->rootfs)
                                break;
                        *p = 'b';
                        /* FALLTHROUGH */
                  case '-':
                        if ((c = *p) == 'a')
                                od->boothowto &= ~RB_SINGLE;
                        else if (c == 'b')
                                od->boothowto |= RB_ASKNAME;
                        else
                                BOOT_FLAG(c, od->boothowto);
                        break;
                  case '.':
                        od->ostype = p;
                        break;
                  case '/':
                        od->osname = --p;
                        break;
                  default:
                        return -1;
                }

                while ((c = *p) && !isspace(c))
                        p += 1;
        }

done:
        c = od->ostype[0];
        if (isupper(c))
                c = tolower(c);

        switch (c) {
        case 'n':               /* NetBSD */
                return 0;
        case 'l':               /* Linux  */
                return 0x10;
        case 'a':               /* ASV    */
                return 0x40;
        case 't':               /* TOS    */
                return 0x80;
        default:
                return -1;
        }
}

int
load_booter(osdsc_t *od)
{
        int             fd = -1;
        u_char          *bstart = (u_char *)(LOADADDR3);
        int             bsize;
        char            *fname;
        char            *boot_names[] = {       /* 3rd level boot names   */
                                "/boot.atari",  /* in order of preference */
                                "/boot",
                                "/boot.ata",
                                NULL };         /* NULL terminated!       */

        /*
         * Read booter's exec-header.
         */
        for (fname = boot_names[0]; fname != NULL; fname++) {
                if ((fd = open(fname, 0)) < 0)
                        printf("Cannot open '%s'\n", fname);
                else
                        break;
        }
        if (fd < 0)
                return -1;
        while ((bsize = read(fd, bstart, 1024)) > 0) {
                bstart += bsize;
        }
        close(fd);
        return 0;
}

void
_rtt(void)
{

        printf("Halting...\n");
        for (;;)
                ;
}