Exemplo n.º 1
0
static void zipl_load_segment(ComponentEntry *entry)
{
    const int max_entries = (MAX_SECTOR_SIZE / sizeof(ScsiBlockPtr));
    ScsiBlockPtr *bprs = (void *)sec;
    const int bprs_size = sizeof(sec);
    block_number_t blockno;
    uint64_t address;
    int i;
    char err_msg[] = "zIPL failed to read BPRS at 0xZZZZZZZZZZZZZZZZ";
    char *blk_no = &err_msg[30]; /* where to print blockno in (those ZZs) */

    blockno = entry->data.blockno;
    address = entry->load_address;

    debug_print_int("loading segment at block", blockno);
    debug_print_int("addr", address);

    do {
        memset(bprs, FREE_SPACE_FILLER, bprs_size);
        fill_hex_val(blk_no, &blockno, sizeof(blockno));
        read_block(blockno, bprs, err_msg);

        for (i = 0;; i++) {
            uint64_t *cur_desc = (void *)&bprs[i];

            blockno = bprs[i].blockno;
            if (!blockno) {
                break;
            }

            /* we need the updated blockno for the next indirect entry in the
               chain, but don't want to advance address */
            if (i == (max_entries - 1)) {
                break;
            }

            if (bprs[i].blockct == 0 && unused_space(&bprs[i + 1],
                sizeof(ScsiBlockPtr))) {
                /* This is a "continue" pointer.
                 * This ptr is the last one in the current script section.
                 * I.e. the next ptr must point to the unused memory area.
                 * The blockno is not zero, so the upper loop must continue
                 * reading next section of BPRS.
                 */
                break;
            }
            address = virtio_load_direct(cur_desc[0], cur_desc[1], 0,
                                         (void *)address);
            IPL_assert(address != -1, "zIPL load segment failed");
        }
    } while (blockno);
}
Exemplo n.º 2
0
static void virtio_setup(uint64_t dev_info)
{
    struct schib schib;
    int i;
    int r;
    bool found = false;
    bool check_devno = false;
    uint16_t dev_no = -1;

    if (dev_info != -1) {
        check_devno = true;
        dev_no = dev_info & 0xffff;
        debug_print_int("device no. ", dev_no);
        blk_schid.ssid = (dev_info >> 16) & 0x3;
        if (blk_schid.ssid != 0) {
            debug_print_int("ssid ", blk_schid.ssid);
            if (enable_mss_facility() != 0) {
                virtio_panic("Failed to enable mss facility\n");
            }
        }
    }
Exemplo n.º 3
0
static void ipl_scsi(void)
{
    ScsiMbr *mbr = (void *)sec;
    uint8_t *ns, *ns_end;
    int program_table_entries = 0;
    const int pte_len = sizeof(ScsiBlockPtr);
    ScsiBlockPtr *prog_table_entry;

    /* The 0-th block (MBR) was already read into sec[] */

    sclp_print("Using SCSI scheme.\n");
    debug_print_int("program table", mbr->blockptr.blockno);

    /* Parse the program table */
    read_block(mbr->blockptr.blockno, sec,
               "Error reading Program Table");

    IPL_assert(magic_match(sec, ZIPL_MAGIC), "No zIPL magic");

    ns_end = sec + virtio_get_block_size();
    for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns++) {
        prog_table_entry = (ScsiBlockPtr *)ns;
        if (!prog_table_entry->blockno) {
            break;
        }

        program_table_entries++;
    }

    debug_print_int("program table entries", program_table_entries);

    IPL_assert(program_table_entries != 0, "Empty Program Table");

    /* Run the default entry */

    prog_table_entry = (ScsiBlockPtr *)(sec + pte_len);

    zipl_run(prog_table_entry); /* no return */
}