root/sys/arch/ews4800mips/stand/common/devopen.c
/*      $NetBSD: devopen.c,v 1.5 2011/12/25 06:09:09 tsutsui Exp $      */

/*-
 * Copyright (c) 2004 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by UCHIYAMA Yasushi.
 *
 * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION OR CONTRIBUTORS
 * 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 <lib/libsa/stand.h>
#include <lib/libkern/libkern.h>

#include <netinet/in.h>
#include <lib/libsa/dev_net.h>
#include <lib/libsa/ufs.h>
#include <lib/libsa/nfs.h>
#include <lib/libsa/dev_net.h>
#include <machine/sbd.h>

#include "local.h"

extern uint8_t kernel_binary[];
extern int kernel_binary_size;

extern struct fs_ops datafs_ops;
extern struct fs_ops bfs_ops;
struct fs_ops ufs_ops = FS_OPS(ufs);
struct fs_ops nfs_ops = FS_OPS(nfs);

extern struct devsw netdevsw;
extern struct devsw dkdevsw;
char fname[16];

/* Referenced by libsa/open.c */
struct fs_ops file_system[1];
int nfsys = 1;
struct devsw devsw[1];
int ndevs = 1;

int
devopen(struct open_file *f, const char *request, char **file)
{
        char *p, *filename;
        int disk, partition;
        void *addr;
        size_t size;

        strcpy(fname, request);

        filename = 0;
        for (p = fname; *p; p++) {
                if (*p == ':') {
                        filename = p + 1;
                        *p = '\0';
                        break;
                }
        }

        if (filename == 0) {    /* not a loader's request. probably ufs_ls() */
                printf("request=%s\n", request);
                f->f_dev = &dkdevsw;
                file_system[0] = ufs_ops;
                devsw[0] = dkdevsw;
                *file = "/";
                return 0;
        }

        /* Data section */
        if (strcmp(fname, "mem") == 0) {
                data_attach(kernel_binary, kernel_binary_size);
                *file = "noname";
                f->f_flags |= F_NODEV;
                file_system[0] = datafs_ops;
                printf("data(compiled):noname\n");
                return 0;
        }

        /* NFS boot */
        if (strcmp(fname, "nfs") == 0) {
                if (!DEVICE_CAPABILITY.network_enabled) {
                        printf("Network disabled.\n");
                        return -1;
                }
                try_bootp = true;
                file_system[0] = nfs_ops;
                f->f_dev = &netdevsw;
                if (*filename == '\0') {
                        printf("set kernel filename. ex.) nfs:netbsd\n");
                        return 1;
                }
                *--filename = '/';
                *file = filename;
                printf("nfs:/%s\n", filename);
                net_open(f);
                return 0;
        }

        /* FD boot */
        if (strcmp(fname, "fd") == 0) {
                printf("floppy(boot):/%s (ustarfs)\n", filename);
                f->f_dev = &dkdevsw;
                file_system[0] = datafs_ops;
                devsw[0] = dkdevsw;
                device_attach(NVSRAM_BOOTDEV_FLOPPYDISK, -1, -1);
                if (!ustarfs_load(filename, &addr, &size))
                        return -1;
                data_attach(addr, size);
                *file = filename;
                return 0;
        }

        /* Disk boot */
        if (strncmp(fname, "sd", 2) == 0) {
                enum fstype fs;
                if (!DEVICE_CAPABILITY.disk_enabled) {
                        printf("Disk disabled.\n");
                        return -1;
                }

                disk = fname[2] - '0';
                partition = fname[3] - 'a';
                if (disk < 0 || disk > 9 || partition < 0 || partition > 15) {
                        fs = FSTYPE_USTARFS;
                        printf("disk(boot):%s ", filename);
                        device_attach(NVSRAM_BOOTDEV_HARDDISK, -1, -1);
                } else {
                        fs = fstype(partition);
                        printf("disk(%d,%d):/%s ",
                            disk, partition, filename);
                        device_attach(NVSRAM_BOOTDEV_HARDDISK, disk, partition);
                }

                switch (fs) {
                case FSTYPE_UFS:
                        printf(" (ufs)\n");
                        f->f_dev = &dkdevsw;
                        file_system[0] = ufs_ops;
                        devsw[0] = dkdevsw;
                        break;
                case FSTYPE_BFS:
                        printf(" (bfs)\n");
                        f->f_flags |= F_NODEV;
                        file_system[0] = bfs_ops;
                        break;
                case FSTYPE_USTARFS:
                        printf(" (ustarfs)\n");
                        f->f_dev = &dkdevsw;
                        file_system[0] = datafs_ops;
                        devsw[0] = dkdevsw;
                        if (!ustarfs_load(filename, &addr, &size))
                                return -1;
                        data_attach(addr, size);
                        break;
                }
                *file = filename;
                return 0;
        }

        printf("%s invalid.\n", fname);

        return -1;
}