~ubuntu-branches/ubuntu/trusty/seabios/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/1.7.2.2.diff/src/boot.c

  • Committer: Package Import Robot
  • Author(s): Michael Tokarev
  • Date: 2013-07-08 21:34:44 UTC
  • mfrom: (1.1.7)
  • Revision ID: package-import@ubuntu.com-20130708213444-6ed9q23j39x143lu
Tags: 1.7.3-1
Multi-Arch: allowed

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Code to load disk image and start system boot.
2
 
//
3
 
// Copyright (C) 2008-2010  Kevin O'Connor <kevin@koconnor.net>
4
 
// Copyright (C) 2002  MandrakeSoft S.A.
5
 
//
6
 
// This file may be distributed under the terms of the GNU LGPLv3 license.
7
 
 
8
 
#include "util.h" // dprintf
9
 
#include "config.h" // CONFIG_*
10
 
#include "disk.h" // cdrom_boot
11
 
#include "bregs.h" // struct bregs
12
 
#include "boot.h" // func defs
13
 
#include "cmos.h" // inb_cmos
14
 
#include "paravirt.h" // qemu_cfg_show_boot_menu
15
 
#include "pci.h" // pci_bdf_to_*
16
 
#include "usb.h" // struct usbdevice_s
17
 
 
18
 
 
19
 
/****************************************************************
20
 
 * Boot priority ordering
21
 
 ****************************************************************/
22
 
 
23
 
static char **Bootorder;
24
 
static int BootorderCount;
25
 
 
26
 
static void
27
 
loadBootOrder(void)
28
 
{
29
 
    if (!CONFIG_BOOTORDER)
30
 
        return;
31
 
 
32
 
    char *f = romfile_loadfile("bootorder", NULL);
33
 
    if (!f)
34
 
        return;
35
 
 
36
 
    int i = 0;
37
 
    BootorderCount = 1;
38
 
    while (f[i]) {
39
 
        if (f[i] == '\n')
40
 
            BootorderCount++;
41
 
        i++;
42
 
    }
43
 
    Bootorder = malloc_tmphigh(BootorderCount*sizeof(char*));
44
 
    if (!Bootorder) {
45
 
        warn_noalloc();
46
 
        free(f);
47
 
        BootorderCount = 0;
48
 
        return;
49
 
    }
50
 
 
51
 
    dprintf(3, "boot order:\n");
52
 
    i = 0;
53
 
    do {
54
 
        Bootorder[i] = f;
55
 
        f = strchr(f, '\n');
56
 
        if (f)
57
 
            *(f++) = '\0';
58
 
        nullTrailingSpace(Bootorder[i]);
59
 
        dprintf(3, "%d: %s\n", i+1, Bootorder[i]);
60
 
        i++;
61
 
    } while (f);
62
 
}
63
 
 
64
 
// See if 'str' starts with 'glob' - if glob contains an '*' character
65
 
// it will match any number of characters in str that aren't a '/' or
66
 
// the next glob character.
67
 
static char *
68
 
glob_prefix(const char *glob, const char *str)
69
 
{
70
 
    for (;;) {
71
 
        if (!*glob && (!*str || *str == '/'))
72
 
            return (char*)str;
73
 
        if (*glob == '*') {
74
 
            if (!*str || *str == '/' || *str == glob[1])
75
 
                glob++;
76
 
            else
77
 
                str++;
78
 
            continue;
79
 
        }
80
 
        if (*glob != *str)
81
 
            return NULL;
82
 
        glob++;
83
 
        str++;
84
 
    }
85
 
}
86
 
 
87
 
// Search the bootorder list for the given glob pattern.
88
 
static int
89
 
find_prio(const char *glob)
90
 
{
91
 
    dprintf(1, "Searching bootorder for: %s\n", glob);
92
 
    int i;
93
 
    for (i = 0; i < BootorderCount; i++)
94
 
        if (glob_prefix(glob, Bootorder[i]))
95
 
            return i+1;
96
 
    return -1;
97
 
}
98
 
 
99
 
#define FW_PCI_DOMAIN "/pci@i0cf8"
100
 
 
101
 
static char *
102
 
build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci)
103
 
{
104
 
    // Build the string path of a bdf - for example: /pci@i0cf8/isa@1,2
105
 
    char *p = buf;
106
 
    if (pci->parent) {
107
 
        p = build_pci_path(p, max, "pci-bridge", pci->parent);
108
 
    } else {
109
 
        if (pci->rootbus)
110
 
            p += snprintf(p, max, "/pci-root@%x", pci->rootbus);
111
 
        p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN);
112
 
    }
113
 
 
114
 
    int dev = pci_bdf_to_dev(pci->bdf), fn = pci_bdf_to_fn(pci->bdf);
115
 
    p += snprintf(p, buf+max-p, "/%s@%x", devname, dev);
116
 
    if (fn)
117
 
        p += snprintf(p, buf+max-p, ",%x", fn);
118
 
    return p;
119
 
}
120
 
 
121
 
int bootprio_find_pci_device(struct pci_device *pci)
122
 
{
123
 
    if (!CONFIG_BOOTORDER)
124
 
        return -1;
125
 
    // Find pci device - for example: /pci@i0cf8/ethernet@5
126
 
    char desc[256];
127
 
    build_pci_path(desc, sizeof(desc), "*", pci);
128
 
    return find_prio(desc);
129
 
}
130
 
 
131
 
int bootprio_find_scsi_device(struct pci_device *pci, int target, int lun)
132
 
{
133
 
    if (!CONFIG_BOOTORDER)
134
 
        return -1;
135
 
    if (!pci)
136
 
        // support only pci machine for now
137
 
        return -1;
138
 
    // Find scsi drive - for example: /pci@i0cf8/scsi@5/channel@0/disk@1,0
139
 
    char desc[256], *p;
140
 
    p = build_pci_path(desc, sizeof(desc), "*", pci);
141
 
    snprintf(p, desc+sizeof(desc)-p, "/*@0/*@%d,%d", target, lun);
142
 
    return find_prio(desc);
143
 
}
144
 
 
145
 
int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave)
146
 
{
147
 
    if (!CONFIG_BOOTORDER)
148
 
        return -1;
149
 
    if (!pci)
150
 
        // support only pci machine for now
151
 
        return -1;
152
 
    // Find ata drive - for example: /pci@i0cf8/ide@1,1/drive@1/disk@0
153
 
    char desc[256], *p;
154
 
    p = build_pci_path(desc, sizeof(desc), "*", pci);
155
 
    snprintf(p, desc+sizeof(desc)-p, "/drive@%x/disk@%x", chanid, slave);
156
 
    return find_prio(desc);
157
 
}
158
 
 
159
 
int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid)
160
 
{
161
 
    if (!CONFIG_BOOTORDER)
162
 
        return -1;
163
 
    if (!pci)
164
 
        // support only pci machine for now
165
 
        return -1;
166
 
    // Find floppy - for example: /pci@i0cf8/isa@1/fdc@03f1/floppy@0
167
 
    char desc[256], *p;
168
 
    p = build_pci_path(desc, sizeof(desc), "isa", pci);
169
 
    snprintf(p, desc+sizeof(desc)-p, "/fdc@%04x/floppy@%x", port, fdid);
170
 
    return find_prio(desc);
171
 
}
172
 
 
173
 
int bootprio_find_pci_rom(struct pci_device *pci, int instance)
174
 
{
175
 
    if (!CONFIG_BOOTORDER)
176
 
        return -1;
177
 
    // Find pci rom - for example: /pci@i0cf8/scsi@3:rom2
178
 
    char desc[256], *p;
179
 
    p = build_pci_path(desc, sizeof(desc), "*", pci);
180
 
    if (instance)
181
 
        snprintf(p, desc+sizeof(desc)-p, ":rom%d", instance);
182
 
    return find_prio(desc);
183
 
}
184
 
 
185
 
int bootprio_find_named_rom(const char *name, int instance)
186
 
{
187
 
    if (!CONFIG_BOOTORDER)
188
 
        return -1;
189
 
    // Find named rom - for example: /rom@genroms/linuxboot.bin
190
 
    char desc[256], *p;
191
 
    p = desc + snprintf(desc, sizeof(desc), "/rom@%s", name);
192
 
    if (instance)
193
 
        snprintf(p, desc+sizeof(desc)-p, ":rom%d", instance);
194
 
    return find_prio(desc);
195
 
}
196
 
 
197
 
static char *
198
 
build_usb_path(char *buf, int max, struct usbhub_s *hub)
199
 
{
200
 
    if (!hub->usbdev)
201
 
        // Root hub - nothing to add.
202
 
        return buf;
203
 
    char *p = build_usb_path(buf, max, hub->usbdev->hub);
204
 
    p += snprintf(p, buf+max-p, "/hub@%x", hub->usbdev->port+1);
205
 
    return p;
206
 
}
207
 
 
208
 
int bootprio_find_usb(struct usbdevice_s *usbdev, int lun)
209
 
{
210
 
    if (!CONFIG_BOOTORDER)
211
 
        return -1;
212
 
    // Find usb - for example: /pci@i0cf8/usb@1,2/storage@1/channel@0/disk@0,0
213
 
    char desc[256], *p;
214
 
    p = build_pci_path(desc, sizeof(desc), "usb", usbdev->hub->cntl->pci);
215
 
    p = build_usb_path(p, desc+sizeof(desc)-p, usbdev->hub);
216
 
    snprintf(p, desc+sizeof(desc)-p, "/storage@%x/*@0/*@0,%d"
217
 
             , usbdev->port+1, lun);
218
 
    int ret = find_prio(desc);
219
 
    if (ret >= 0)
220
 
        return ret;
221
 
    // Try usb-host/redir - for example: /pci@i0cf8/usb@1,2/usb-host@1
222
 
    snprintf(p, desc+sizeof(desc)-p, "/usb-*@%x", usbdev->port+1);
223
 
    return find_prio(desc);
224
 
}
225
 
 
226
 
 
227
 
/****************************************************************
228
 
 * Boot setup
229
 
 ****************************************************************/
230
 
 
231
 
static int CheckFloppySig = 1;
232
 
 
233
 
#define DEFAULT_PRIO           9999
234
 
 
235
 
static int DefaultFloppyPrio = 101;
236
 
static int DefaultCDPrio     = 102;
237
 
static int DefaultHDPrio     = 103;
238
 
static int DefaultBEVPrio    = 104;
239
 
 
240
 
void
241
 
boot_setup(void)
242
 
{
243
 
    if (! CONFIG_BOOT)
244
 
        return;
245
 
 
246
 
    if (!CONFIG_COREBOOT) {
247
 
        // On emulators, get boot order from nvram.
248
 
        if (inb_cmos(CMOS_BIOS_BOOTFLAG1) & 1)
249
 
            CheckFloppySig = 0;
250
 
        u32 bootorder = (inb_cmos(CMOS_BIOS_BOOTFLAG2)
251
 
                         | ((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4));
252
 
        DefaultFloppyPrio = DefaultCDPrio = DefaultHDPrio
253
 
            = DefaultBEVPrio = DEFAULT_PRIO;
254
 
        int i;
255
 
        for (i=101; i<104; i++) {
256
 
            u32 val = bootorder & 0x0f;
257
 
            bootorder >>= 4;
258
 
            switch (val) {
259
 
            case 1: DefaultFloppyPrio = i; break;
260
 
            case 2: DefaultHDPrio = i;     break;
261
 
            case 3: DefaultCDPrio = i;     break;
262
 
            case 4: DefaultBEVPrio = i;    break;
263
 
            }
264
 
        }
265
 
    }
266
 
 
267
 
    loadBootOrder();
268
 
}
269
 
 
270
 
 
271
 
/****************************************************************
272
 
 * BootList handling
273
 
 ****************************************************************/
274
 
 
275
 
struct bootentry_s {
276
 
    int type;
277
 
    union {
278
 
        u32 data;
279
 
        struct segoff_s vector;
280
 
        struct drive_s *drive;
281
 
    };
282
 
    int priority;
283
 
    const char *description;
284
 
    struct bootentry_s *next;
285
 
};
286
 
static struct bootentry_s *BootList;
287
 
 
288
 
#define IPL_TYPE_FLOPPY      0x01
289
 
#define IPL_TYPE_HARDDISK    0x02
290
 
#define IPL_TYPE_CDROM       0x03
291
 
#define IPL_TYPE_CBFS        0x20
292
 
#define IPL_TYPE_BEV         0x80
293
 
#define IPL_TYPE_BCV         0x81
294
 
#define IPL_TYPE_HALT        0xf0
295
 
 
296
 
static void
297
 
bootentry_add(int type, int prio, u32 data, const char *desc)
298
 
{
299
 
    if (! CONFIG_BOOT)
300
 
        return;
301
 
    struct bootentry_s *be = malloc_tmp(sizeof(*be));
302
 
    if (!be) {
303
 
        warn_noalloc();
304
 
        return;
305
 
    }
306
 
    be->type = type;
307
 
    be->priority = prio;
308
 
    be->data = data;
309
 
    be->description = desc ?: "?";
310
 
    dprintf(3, "Registering bootable: %s (type:%d prio:%d data:%x)\n"
311
 
            , be->description, type, prio, data);
312
 
 
313
 
    // Add entry in sorted order.
314
 
    struct bootentry_s **pprev;
315
 
    for (pprev = &BootList; *pprev; pprev = &(*pprev)->next) {
316
 
        struct bootentry_s *pos = *pprev;
317
 
        if (be->priority < pos->priority)
318
 
            break;
319
 
        if (be->priority > pos->priority)
320
 
            continue;
321
 
        if (be->type < pos->type)
322
 
            break;
323
 
        if (be->type > pos->type)
324
 
            continue;
325
 
        if (be->type <= IPL_TYPE_CDROM
326
 
            && (be->drive->type < pos->drive->type
327
 
                || (be->drive->type == pos->drive->type
328
 
                    && be->drive->cntl_id < pos->drive->cntl_id)))
329
 
            break;
330
 
    }
331
 
    be->next = *pprev;
332
 
    *pprev = be;
333
 
}
334
 
 
335
 
// Return the given priority if it's set - defaultprio otherwise.
336
 
static inline int defPrio(int priority, int defaultprio) {
337
 
    return (priority < 0) ? defaultprio : priority;
338
 
}
339
 
 
340
 
// Add a BEV vector for a given pnp compatible option rom.
341
 
void
342
 
boot_add_bev(u16 seg, u16 bev, u16 desc, int prio)
343
 
{
344
 
    bootentry_add(IPL_TYPE_BEV, defPrio(prio, DefaultBEVPrio)
345
 
                  , SEGOFF(seg, bev).segoff
346
 
                  , desc ? MAKE_FLATPTR(seg, desc) : "Unknown");
347
 
    DefaultBEVPrio = DEFAULT_PRIO;
348
 
}
349
 
 
350
 
// Add a bcv entry for an expansion card harddrive or legacy option rom
351
 
void
352
 
boot_add_bcv(u16 seg, u16 ip, u16 desc, int prio)
353
 
{
354
 
    bootentry_add(IPL_TYPE_BCV, defPrio(prio, DefaultHDPrio)
355
 
                  , SEGOFF(seg, ip).segoff
356
 
                  , desc ? MAKE_FLATPTR(seg, desc) : "Legacy option rom");
357
 
}
358
 
 
359
 
void
360
 
boot_add_floppy(struct drive_s *drive_g, const char *desc, int prio)
361
 
{
362
 
    bootentry_add(IPL_TYPE_FLOPPY, defPrio(prio, DefaultFloppyPrio)
363
 
                  , (u32)drive_g, desc);
364
 
}
365
 
 
366
 
void
367
 
boot_add_hd(struct drive_s *drive_g, const char *desc, int prio)
368
 
{
369
 
    bootentry_add(IPL_TYPE_HARDDISK, defPrio(prio, DefaultHDPrio)
370
 
                  , (u32)drive_g, desc);
371
 
}
372
 
 
373
 
void
374
 
boot_add_cd(struct drive_s *drive_g, const char *desc, int prio)
375
 
{
376
 
    bootentry_add(IPL_TYPE_CDROM, defPrio(prio, DefaultCDPrio)
377
 
                  , (u32)drive_g, desc);
378
 
}
379
 
 
380
 
// Add a CBFS payload entry
381
 
void
382
 
boot_add_cbfs(void *data, const char *desc, int prio)
383
 
{
384
 
    bootentry_add(IPL_TYPE_CBFS, defPrio(prio, DEFAULT_PRIO), (u32)data, desc);
385
 
}
386
 
 
387
 
 
388
 
/****************************************************************
389
 
 * Boot menu and BCV execution
390
 
 ****************************************************************/
391
 
 
392
 
#define DEFAULT_BOOTMENU_WAIT 2500
393
 
 
394
 
// Show IPL option menu.
395
 
static void
396
 
interactive_bootmenu(void)
397
 
{
398
 
    if (! CONFIG_BOOTMENU || ! qemu_cfg_show_boot_menu())
399
 
        return;
400
 
 
401
 
    while (get_keystroke(0) >= 0)
402
 
        ;
403
 
 
404
 
    printf("\nPress F12 for boot menu.\n\n");
405
 
 
406
 
    u32 menutime = romfile_loadint("etc/boot-menu-wait", DEFAULT_BOOTMENU_WAIT);
407
 
    enable_bootsplash();
408
 
    int scan_code = get_keystroke(menutime);
409
 
    disable_bootsplash();
410
 
    if (scan_code != 0x86)
411
 
        /* not F12 */
412
 
        return;
413
 
 
414
 
    while (get_keystroke(0) >= 0)
415
 
        ;
416
 
 
417
 
    printf("Select boot device:\n\n");
418
 
    wait_threads();
419
 
 
420
 
    // Show menu items
421
 
    struct bootentry_s *pos = BootList;
422
 
    int maxmenu = 0;
423
 
    while (pos) {
424
 
        char desc[60];
425
 
        maxmenu++;
426
 
        printf("%d. %s\n", maxmenu
427
 
               , strtcpy(desc, pos->description, ARRAY_SIZE(desc)));
428
 
        pos = pos->next;
429
 
    }
430
 
 
431
 
    // Get key press
432
 
    for (;;) {
433
 
        scan_code = get_keystroke(1000);
434
 
        if (scan_code >= 1 && scan_code <= maxmenu+1)
435
 
            break;
436
 
    }
437
 
    printf("\n");
438
 
    if (scan_code == 0x01)
439
 
        // ESC
440
 
        return;
441
 
 
442
 
    // Find entry and make top priority.
443
 
    int choice = scan_code - 1;
444
 
    struct bootentry_s **pprev = &BootList;
445
 
    while (--choice)
446
 
        pprev = &(*pprev)->next;
447
 
    pos = *pprev;
448
 
    *pprev = pos->next;
449
 
    pos->next = BootList;
450
 
    BootList = pos;
451
 
    pos->priority = 0;
452
 
}
453
 
 
454
 
// BEV (Boot Execution Vector) list
455
 
struct bev_s {
456
 
    int type;
457
 
    u32 vector;
458
 
};
459
 
static struct bev_s BEV[20];
460
 
static int BEVCount;
461
 
static int HaveHDBoot, HaveFDBoot;
462
 
 
463
 
static void
464
 
add_bev(int type, u32 vector)
465
 
{
466
 
    if (type == IPL_TYPE_HARDDISK && HaveHDBoot++)
467
 
        return;
468
 
    if (type == IPL_TYPE_FLOPPY && HaveFDBoot++)
469
 
        return;
470
 
    if (BEVCount >= ARRAY_SIZE(BEV))
471
 
        return;
472
 
    struct bev_s *bev = &BEV[BEVCount++];
473
 
    bev->type = type;
474
 
    bev->vector = vector;
475
 
}
476
 
 
477
 
// Prepare for boot - show menu and run bcvs.
478
 
void
479
 
boot_prep(void)
480
 
{
481
 
    if (! CONFIG_BOOT) {
482
 
        wait_threads();
483
 
        return;
484
 
    }
485
 
 
486
 
    // XXX - show available drives?
487
 
 
488
 
    // Allow user to modify BCV/IPL order.
489
 
    interactive_bootmenu();
490
 
    wait_threads();
491
 
 
492
 
    int haltprio = find_prio("HALT");
493
 
    if (haltprio >= 0)
494
 
        bootentry_add(IPL_TYPE_HALT, haltprio, 0, "HALT");
495
 
 
496
 
    // Map drives and populate BEV list
497
 
    struct bootentry_s *pos = BootList;
498
 
    while (pos) {
499
 
        switch (pos->type) {
500
 
        case IPL_TYPE_BCV:
501
 
            call_bcv(pos->vector.seg, pos->vector.offset);
502
 
            add_bev(IPL_TYPE_HARDDISK, 0);
503
 
            break;
504
 
        case IPL_TYPE_FLOPPY:
505
 
            map_floppy_drive(pos->drive);
506
 
            add_bev(IPL_TYPE_FLOPPY, 0);
507
 
            break;
508
 
        case IPL_TYPE_HARDDISK:
509
 
            map_hd_drive(pos->drive);
510
 
            add_bev(IPL_TYPE_HARDDISK, 0);
511
 
            break;
512
 
        case IPL_TYPE_CDROM:
513
 
            map_cd_drive(pos->drive);
514
 
            // NO BREAK
515
 
        default:
516
 
            add_bev(pos->type, pos->data);
517
 
            break;
518
 
        }
519
 
        pos = pos->next;
520
 
    }
521
 
 
522
 
    // If nothing added a floppy/hd boot - add it manually.
523
 
    add_bev(IPL_TYPE_FLOPPY, 0);
524
 
    add_bev(IPL_TYPE_HARDDISK, 0);
525
 
}
526
 
 
527
 
 
528
 
/****************************************************************
529
 
 * Boot code (int 18/19)
530
 
 ****************************************************************/
531
 
 
532
 
// Jump to a bootup entry point.
533
 
static void
534
 
call_boot_entry(struct segoff_s bootsegip, u8 bootdrv)
535
 
{
536
 
    dprintf(1, "Booting from %04x:%04x\n", bootsegip.seg, bootsegip.offset);
537
 
    struct bregs br;
538
 
    memset(&br, 0, sizeof(br));
539
 
    br.flags = F_IF;
540
 
    br.code = bootsegip;
541
 
    // Set the magic number in ax and the boot drive in dl.
542
 
    br.dl = bootdrv;
543
 
    br.ax = 0xaa55;
544
 
    farcall16(&br);
545
 
}
546
 
 
547
 
// Boot from a disk (either floppy or harddrive)
548
 
static void
549
 
boot_disk(u8 bootdrv, int checksig)
550
 
{
551
 
    u16 bootseg = 0x07c0;
552
 
 
553
 
    // Read sector
554
 
    struct bregs br;
555
 
    memset(&br, 0, sizeof(br));
556
 
    br.flags = F_IF;
557
 
    br.dl = bootdrv;
558
 
    br.es = bootseg;
559
 
    br.ah = 2;
560
 
    br.al = 1;
561
 
    br.cl = 1;
562
 
    call16_int(0x13, &br);
563
 
 
564
 
    if (br.flags & F_CF) {
565
 
        printf("Boot failed: could not read the boot disk\n\n");
566
 
        return;
567
 
    }
568
 
 
569
 
    if (checksig) {
570
 
        struct mbr_s *mbr = (void*)0;
571
 
        if (GET_FARVAR(bootseg, mbr->signature) != MBR_SIGNATURE) {
572
 
            printf("Boot failed: not a bootable disk\n\n");
573
 
            return;
574
 
        }
575
 
    }
576
 
 
577
 
    /* Canonicalize bootseg:bootip */
578
 
    u16 bootip = (bootseg & 0x0fff) << 4;
579
 
    bootseg &= 0xf000;
580
 
 
581
 
    call_boot_entry(SEGOFF(bootseg, bootip), bootdrv);
582
 
}
583
 
 
584
 
// Boot from a CD-ROM
585
 
static void
586
 
boot_cdrom(struct drive_s *drive_g)
587
 
{
588
 
    if (! CONFIG_CDROM_BOOT)
589
 
        return;
590
 
    printf("Booting from DVD/CD...\n");
591
 
 
592
 
    int status = cdrom_boot(drive_g);
593
 
    if (status) {
594
 
        printf("Boot failed: Could not read from CDROM (code %04x)\n", status);
595
 
        return;
596
 
    }
597
 
 
598
 
    u8 bootdrv = CDEmu.emulated_extdrive;
599
 
    u16 bootseg = CDEmu.load_segment;
600
 
    /* Canonicalize bootseg:bootip */
601
 
    u16 bootip = (bootseg & 0x0fff) << 4;
602
 
    bootseg &= 0xf000;
603
 
 
604
 
    call_boot_entry(SEGOFF(bootseg, bootip), bootdrv);
605
 
}
606
 
 
607
 
// Boot from a CBFS payload
608
 
static void
609
 
boot_cbfs(struct cbfs_file *file)
610
 
{
611
 
    if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH)
612
 
        return;
613
 
    printf("Booting from CBFS...\n");
614
 
    cbfs_run_payload(file);
615
 
}
616
 
 
617
 
// Boot from a BEV entry on an optionrom.
618
 
static void
619
 
boot_rom(u32 vector)
620
 
{
621
 
    printf("Booting from ROM...\n");
622
 
    struct segoff_s so;
623
 
    so.segoff = vector;
624
 
    call_boot_entry(so, 0);
625
 
}
626
 
 
627
 
// Unable to find bootable device - warn user and eventually retry.
628
 
static void
629
 
boot_fail(void)
630
 
{
631
 
    u32 retrytime = romfile_loadint("etc/boot-fail-wait", 60*1000);
632
 
    if (retrytime == (u32)-1)
633
 
        printf("No bootable device.\n");
634
 
    else
635
 
        printf("No bootable device.  Retrying in %d seconds.\n", retrytime/1000);
636
 
    // Wait for 'retrytime' milliseconds and then reboot.
637
 
    u32 end = calc_future_timer(retrytime);
638
 
    for (;;) {
639
 
        if (retrytime != (u32)-1 && check_timer(end))
640
 
            break;
641
 
        yield_toirq();
642
 
    }
643
 
    printf("Rebooting.\n");
644
 
    struct bregs br;
645
 
    memset(&br, 0, sizeof(br));
646
 
    br.code = SEGOFF(SEG_BIOS, (u32)reset_vector);
647
 
    farcall16big(&br);
648
 
}
649
 
 
650
 
// Determine next boot method and attempt a boot using it.
651
 
static void
652
 
do_boot(int seq_nr)
653
 
{
654
 
    if (! CONFIG_BOOT)
655
 
        panic("Boot support not compiled in.\n");
656
 
 
657
 
    if (seq_nr >= BEVCount)
658
 
        boot_fail();
659
 
 
660
 
    // Boot the given BEV type.
661
 
    struct bev_s *ie = &BEV[seq_nr];
662
 
    switch (ie->type) {
663
 
    case IPL_TYPE_FLOPPY:
664
 
        printf("Booting from Floppy...\n");
665
 
        boot_disk(0x00, CheckFloppySig);
666
 
        break;
667
 
    case IPL_TYPE_HARDDISK:
668
 
        printf("Booting from Hard Disk...\n");
669
 
        boot_disk(0x80, 1);
670
 
        break;
671
 
    case IPL_TYPE_CDROM:
672
 
        boot_cdrom((void*)ie->vector);
673
 
        break;
674
 
    case IPL_TYPE_CBFS:
675
 
        boot_cbfs((void*)ie->vector);
676
 
        break;
677
 
    case IPL_TYPE_BEV:
678
 
        boot_rom(ie->vector);
679
 
        break;
680
 
    case IPL_TYPE_HALT:
681
 
        boot_fail();
682
 
        break;
683
 
    }
684
 
 
685
 
    // Boot failed: invoke the boot recovery function
686
 
    struct bregs br;
687
 
    memset(&br, 0, sizeof(br));
688
 
    br.flags = F_IF;
689
 
    call16_int(0x18, &br);
690
 
}
691
 
 
692
 
int BootSequence VARLOW = -1;
693
 
 
694
 
// Boot Failure recovery: try the next device.
695
 
void VISIBLE32FLAT
696
 
handle_18(void)
697
 
{
698
 
    debug_serial_setup();
699
 
    debug_enter(NULL, DEBUG_HDL_18);
700
 
    int seq = BootSequence + 1;
701
 
    BootSequence = seq;
702
 
    do_boot(seq);
703
 
}
704
 
 
705
 
// INT 19h Boot Load Service Entry Point
706
 
void VISIBLE32FLAT
707
 
handle_19(void)
708
 
{
709
 
    debug_serial_setup();
710
 
    debug_enter(NULL, DEBUG_HDL_19);
711
 
    BootSequence = 0;
712
 
    do_boot(0);
713
 
}