source: bootcd/isolinux/syslinux-6.03/com32/elflink/ldlinux/chainboot.c @ e16e8f2

Last change on this file since e16e8f2 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 3.9 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *   
3 *   Copyright 2012 Intel Corporation, author: H. Peter Anvin
4 *
5 *   This program is free software; you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
8 *   Boston MA 02110-1301, USA; either version 2 of the License, or
9 *   (at your option) any later version; incorporated herein by reference.
10 *
11 * ----------------------------------------------------------------------- */
12
13/*
14 * chainbooting - replace the current bootloader completely.  This
15 * is BIOS-specific.
16 */
17
18#include <fcntl.h>
19#include <stdlib.h>
20#include <string.h>
21#include <stdio.h>
22#include <dprintf.h>
23
24#include <com32.h>
25#include <sys/exec.h>
26#include <sys/io.h>
27#include "core.h"
28#include "menu.h"
29#include "fs.h"
30#include "config.h"
31#include "localboot.h"
32#include "bios.h"
33
34#include <syslinux/boot.h>
35#include <syslinux/bootrm.h>
36#include <syslinux/movebits.h>
37#include <syslinux/config.h>
38
39void chainboot_file(const char *file, uint32_t type)
40{
41    uint8_t keeppxe = 0;
42    const union syslinux_derivative_info *sdi;
43    struct syslinux_rm_regs regs;
44    struct syslinux_movelist *fraglist = NULL;
45    struct syslinux_memmap *mmap = NULL;
46    struct com32_filedata fd;
47    com32sys_t reg;
48    char *stack;
49    void *buf;
50    int rv, max, size;
51   
52    max = 0xA0000;              /* Maximum load */
53    buf = malloc(max);
54    if (!buf)
55        goto bail;
56   
57    rv = open_file(file, O_RDONLY, &fd);
58    if (rv == -1)
59        goto bail;
60   
61    reg.eax.l = max;
62    reg.ebx.l = 0;
63    reg.edx.w[0] = 0;
64    reg.edi.l = (uint32_t)buf;
65    reg.ebp.l = -1;     /* XXX: limit? */
66    reg.esi.w[0] = rv;
67
68    pm_load_high(&reg);
69
70    size = reg.edi.l - (unsigned long)buf;
71    if (size > 0xA0000 - 0x7C00) {
72        printf("Too large for a boostrap (need LINUX instead of KERNEL?)\n");
73        goto bail;
74    }
75
76    mmap = syslinux_memory_map();
77    if (!mmap)
78        goto bail;
79
80    sdi = syslinux_derivative_info();
81
82    memset(&regs, 0, sizeof(regs));
83    regs.ip = 0x7c00;
84
85    if (sdi->c.filesystem == SYSLINUX_FS_SYSLINUX ||
86        sdi->c.filesystem == SYSLINUX_FS_EXTLINUX) {
87        if (syslinux_add_movelist(&fraglist, 0x800 - 18,
88                                  (addr_t)sdi->r.esbx, 16))
89            goto bail;
90
91        /* DS:SI points to partition info */
92        regs.esi.l = 0x800 - 18;
93    }
94
95    /*
96     * For a BSS boot sector we have to transfer the
97     * superblock.
98     */
99    if (sdi->c.filesystem == SYSLINUX_FS_SYSLINUX &&
100        type == IMAGE_TYPE_BSS && this_fs->fs_ops->copy_super(buf))
101        goto bail;
102
103    if (sdi->c.filesystem == SYSLINUX_FS_PXELINUX) {
104        keeppxe = 0x03;         /* Chainloading + keep PXE */
105        stack = (char *)sdi->r.fssi;
106
107        /*
108         * Set up the registers with their initial values
109         */
110
111        regs.eax.l = *(uint32_t *)&stack[36];
112        regs.ecx.l = *(uint32_t *)&stack[32];
113        regs.edx.l = *(uint32_t *)&stack[28];
114        regs.ebx.l = *(uint32_t *)&stack[24];
115        regs.esp.l = sdi->rr.r.esi.w[0] + 44;
116        regs.ebp.l = *(uint32_t *)&stack[16];
117        regs.esi.l = *(uint32_t *)&stack[12];
118        regs.edi.l = *(uint32_t *)&stack[8];
119        regs.es = *(uint16_t *)&stack[4];
120        regs.ss = sdi->rr.r.fs;
121        regs.ds = *(uint16_t *)&stack[6];
122        regs.fs = *(uint16_t *)&stack[2];
123        regs.gs = *(uint16_t *)&stack[0];
124    } else {
125        const uint16_t *esdi = (const uint16_t *)sdi->disk.esdi_ptr;
126
127        regs.esp.l = (uint16_t)(unsigned long)StackBuf + 44;
128
129        /*
130         * DON'T DO THIS FOR PXELINUX...
131         * For PXE, ES:BX -> PXENV+, and this would
132         * corrupt that use.
133         *
134         * Restore ES:DI -> $PnP (if we were ourselves
135         * called that way...)
136         */
137        regs.edi.w[0] = esdi[0]; /* New DI */
138        regs.es       = esdi[2]; /* New ES */
139
140        regs.edx.l    = sdi->rr.r.edx.b[0]; /* Drive number -> DL */
141    }
142
143    if (syslinux_add_movelist(&fraglist, 0x7c00, (addr_t)buf, size))
144        goto bail;
145
146    syslinux_shuffle_boot_rm(fraglist, mmap, keeppxe, &regs);
147
148bail:
149    if (fraglist)
150        syslinux_free_movelist(fraglist);
151    if (mmap)
152        syslinux_free_memmap(mmap);
153    if (buf)
154        free(buf);
155    return;
156}
Note: See TracBrowser for help on using the repository browser.