/*
 * S390 virtio-ccw loading program
 *
 * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 * your option) any later version. See the COPYING file in the top-level
 * directory.
 */

#include "s390-ccw.h"
#include "virtio.h"

char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
static SubChannelId blk_schid = { .one = 1 };
IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
static char loadparm[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

const unsigned char ebc2asc[256] =
      /* 0123456789abcdef0123456789abcdef */
        "................................" /* 1F */
        "................................" /* 3F */
        " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */
        "-/.........,%_>?.........`:#@'=\""/* 7F */
        ".abcdefghi.......jklmnopqr......" /* 9F */
        "..stuvwxyz......................" /* BF */
        ".ABCDEFGHI.......JKLMNOPQR......" /* DF */
        "..STUVWXYZ......0123456789......";/* FF */

/*
 * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
 * a subsystem-identification is at 184-187 and bytes 188-191 are zero
 * after list-directed-IPL and ccw-IPL.
 */
void write_subsystem_identification(void)
{
    SubChannelId *schid = (SubChannelId *) 184;
    uint32_t *zeroes = (uint32_t *) 188;

    *schid = blk_schid;
    *zeroes = 0;
}

void panic(const char *string)
{
    sclp_print(string);
    disabled_wait();
    while (1) { }
}

unsigned int get_loadparm_index(void)
{
    const char *lp = loadparm;
    int i;
    unsigned int idx = 0;

    for (i = 0; i < 8; i++) {
        char c = lp[i];

        if (c < '0' || c > '9') {
            break;
        }

        idx *= 10;
        idx += c - '0';
    }

    return idx;
}

static bool find_dev(Schib *schib, int dev_no)
{
    int i, r;

    for (i = 0; i < 0x10000; i++) {
        blk_schid.sch_no = i;
        r = stsch_err(blk_schid, schib);
        if ((r == 3) || (r == -EIO)) {
            break;
        }
        if (!schib->pmcw.dnv) {
            continue;
        }
        if (!virtio_is_supported(blk_schid)) {
            continue;
        }
        /* Skip net devices since no IPLB is created and therefore no
         * no network bootloader has been loaded
         */
        if (virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
            continue;
        }
        if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) {
            return true;
        }
    }

    return false;
}

static void virtio_setup(void)
{
    Schib schib;
    int ssid;
    bool found = false;
    uint16_t dev_no;
    char ldp[] = "LOADPARM=[________]\n";
    VDev *vdev = virtio_get_device();

    /*
     * We unconditionally enable mss support. In every sane configuration,
     * this will succeed; and even if it doesn't, stsch_err() can deal
     * with the consequences.
     */
    enable_mss_facility();

    sclp_get_loadparm_ascii(loadparm);
    memcpy(ldp + 10, loadparm, 8);
    sclp_print(ldp);

    if (store_iplb(&iplb)) {
        switch (iplb.pbt) {
        case S390_IPL_TYPE_CCW:
            dev_no = iplb.ccw.devno;
            debug_print_int("device no. ", dev_no);
            blk_schid.ssid = iplb.ccw.ssid & 0x3;
            debug_print_int("ssid ", blk_schid.ssid);
            found = find_dev(&schib, dev_no);
            break;
        case S390_IPL_TYPE_QEMU_SCSI:
            vdev->scsi_device_selected = true;
            vdev->selected_scsi_device.channel = iplb.scsi.channel;
            vdev->selected_scsi_device.target = iplb.scsi.target;
            vdev->selected_scsi_device.lun = iplb.scsi.lun;
            blk_schid.ssid = iplb.scsi.ssid & 0x3;
            found = find_dev(&schib, iplb.scsi.devno);
            break;
        default:
            panic("List-directed IPL not supported yet!\n");
        }
    } else {
        for (ssid = 0; ssid < 0x3; ssid++) {
            blk_schid.ssid = ssid;
            found = find_dev(&schib, -1);
            if (found) {
                break;
            }
        }
    }

    IPL_assert(found, "No virtio device found");

    if (virtio_get_device_type() == VIRTIO_ID_NET) {
        sclp_print("Network boot device detected\n");
        vdev->netboot_start_addr = iplb.ccw.netboot_start_addr;
    } else {
        virtio_setup_device(blk_schid);

        IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected");
    }
}

int main(void)
{
    sclp_setup();
    virtio_setup();

    zipl_load(); /* no return */

    panic("Failed to load OS from hard disk\n");
    return 0; /* make compiler happy */
}
