~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/arch/x86/image/com32.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License as
 
6
 * published by the Free Software Foundation; either version 2 of the
 
7
 * License, or any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but
 
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
17
 * 02110-1301, USA.
 
18
 */
 
19
 
 
20
/**
 
21
 * @file
 
22
 *
 
23
 * SYSLINUX COM32 image format
 
24
 *
 
25
 */
 
26
 
 
27
FILE_LICENCE ( GPL2_OR_LATER );
 
28
 
 
29
#include <stdint.h>
 
30
#include <stdlib.h>
 
31
#include <string.h>
 
32
#include <strings.h>
 
33
#include <errno.h>
 
34
#include <assert.h>
 
35
#include <realmode.h>
 
36
#include <basemem.h>
 
37
#include <comboot.h>
 
38
#include <ipxe/uaccess.h>
 
39
#include <ipxe/image.h>
 
40
#include <ipxe/segment.h>
 
41
#include <ipxe/init.h>
 
42
#include <ipxe/io.h>
 
43
#include <ipxe/console.h>
 
44
 
 
45
/**
 
46
 * Execute COMBOOT image
 
47
 *
 
48
 * @v image             COM32 image
 
49
 * @ret rc              Return status code
 
50
 */
 
51
static int com32_exec_loop ( struct image *image ) {
 
52
        struct memory_map memmap;
 
53
        unsigned int i;
 
54
        int state;
 
55
        uint32_t avail_mem_top;
 
56
 
 
57
        state = rmsetjmp ( comboot_return );
 
58
 
 
59
        switch ( state ) {
 
60
        case 0: /* First time through; invoke COM32 program */
 
61
 
 
62
                /* Get memory map */
 
63
                get_memmap ( &memmap );
 
64
 
 
65
                /* Find end of block covering COM32 image loading area */
 
66
                for ( i = 0, avail_mem_top = 0 ; i < memmap.count ; i++ ) {
 
67
                        if ( (memmap.regions[i].start <= COM32_START_PHYS) &&
 
68
                             (memmap.regions[i].end > COM32_START_PHYS + image->len) ) {
 
69
                                avail_mem_top = memmap.regions[i].end;
 
70
                                break;
 
71
                        }
 
72
                }
 
73
 
 
74
                DBGC ( image, "COM32 %p: available memory top = 0x%x\n",
 
75
                       image, avail_mem_top );
 
76
 
 
77
                assert ( avail_mem_top != 0 );
 
78
 
 
79
                /* Hook COMBOOT API interrupts */
 
80
                hook_comboot_interrupts();
 
81
 
 
82
                /* Unregister image, so that a "boot" command doesn't
 
83
                 * throw us into an execution loop.  We never
 
84
                 * reregister ourselves; COMBOOT images expect to be
 
85
                 * removed on exit.
 
86
                 */
 
87
                unregister_image ( image );
 
88
 
 
89
                __asm__ __volatile__ ( PHYS_CODE (
 
90
                        /* Preserve registers */
 
91
                        "pushal\n\t"
 
92
                        /* Preserve stack pointer */
 
93
                        "subl $4, %k0\n\t"
 
94
                        "movl %%esp, (%k0)\n\t"
 
95
                        /* Switch to COM32 stack */
 
96
                        "movl %k0, %%esp\n\t"
 
97
                        /* Enable interrupts */
 
98
                        "sti\n\t"
 
99
                        /* Construct stack frame */
 
100
                        "pushl %k1\n\t"
 
101
                        "pushl %k2\n\t"
 
102
                        "pushl %k3\n\t"
 
103
                        "pushl %k4\n\t"
 
104
                        "pushl %k5\n\t"
 
105
                        "pushl %k6\n\t"
 
106
                        "pushl $6\n\t"
 
107
                        /* Call COM32 entry point */
 
108
                        "movl %k7, %k0\n\t"
 
109
                        "call *%k0\n\t"
 
110
                        /* Disable interrupts */
 
111
                        "cli\n\t"
 
112
                        /* Restore stack pointer */
 
113
                        "movl 24(%%esp), %%esp\n\t"
 
114
                        /* Restore registers */
 
115
                        "popal\n\t" )
 
116
                        :
 
117
                        : "r" ( avail_mem_top ),
 
118
                          "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
 
119
                          "r" ( virt_to_phys ( com32_farcall_wrapper ) ),
 
120
                          "r" ( get_fbms() * 1024 - ( COM32_BOUNCE_SEG << 4 ) ),
 
121
                          "i" ( COM32_BOUNCE_SEG << 4 ),
 
122
                          "r" ( virt_to_phys ( com32_intcall_wrapper ) ),
 
123
                          "r" ( virt_to_phys ( image->cmdline ?
 
124
                                               image->cmdline : "" ) ),
 
125
                          "i" ( COM32_START_PHYS )
 
126
                        : "memory" );
 
127
                DBGC ( image, "COM32 %p: returned\n", image );
 
128
                break;
 
129
 
 
130
        case COMBOOT_EXIT:
 
131
                DBGC ( image, "COM32 %p: exited\n", image );
 
132
                break;
 
133
 
 
134
        case COMBOOT_EXIT_RUN_KERNEL:
 
135
                assert ( image->replacement );
 
136
                DBGC ( image, "COM32 %p: exited to run kernel %s\n",
 
137
                       image, image->replacement->name );
 
138
                break;
 
139
 
 
140
        case COMBOOT_EXIT_COMMAND:
 
141
                DBGC ( image, "COM32 %p: exited after executing command\n",
 
142
                       image );
 
143
                break;
 
144
 
 
145
        default:
 
146
                assert ( 0 );
 
147
                break;
 
148
        }
 
149
 
 
150
        unhook_comboot_interrupts();
 
151
        comboot_force_text_mode();
 
152
 
 
153
        return 0;
 
154
}
 
155
 
 
156
/**
 
157
 * Check image name extension
 
158
 *
 
159
 * @v image             COM32 image
 
160
 * @ret rc              Return status code
 
161
 */
 
162
static int com32_identify ( struct image *image ) {
 
163
        const char *ext;
 
164
        static const uint8_t magic[] = { 0xB8, 0xFF, 0x4C, 0xCD, 0x21 };
 
165
        uint8_t buf[5];
 
166
 
 
167
        if ( image->len >= 5 ) {
 
168
                /* Check for magic number
 
169
                 * mov eax,21cd4cffh
 
170
                 * B8 FF 4C CD 21
 
171
                 */
 
172
                copy_from_user ( buf, image->data, 0, sizeof(buf) );
 
173
                if ( ! memcmp ( buf, magic, sizeof(buf) ) ) {
 
174
                        DBGC ( image, "COM32 %p: found magic number\n",
 
175
                               image );
 
176
                        return 0;
 
177
                }
 
178
        }
 
179
 
 
180
        /* Magic number not found; check filename extension */
 
181
 
 
182
        ext = strrchr( image->name, '.' );
 
183
 
 
184
        if ( ! ext ) {
 
185
                DBGC ( image, "COM32 %p: no extension\n",
 
186
                       image );
 
187
                return -ENOEXEC;
 
188
        }
 
189
 
 
190
        ++ext;
 
191
 
 
192
        if ( strcasecmp( ext, "c32" ) ) {
 
193
                DBGC ( image, "COM32 %p: unrecognized extension %s\n",
 
194
                       image, ext );
 
195
                return -ENOEXEC;
 
196
        }
 
197
 
 
198
        return 0;
 
199
}
 
200
 
 
201
 
 
202
/**
 
203
 * Load COM32 image into memory
 
204
 * @v image             COM32 image
 
205
 * @ret rc              Return status code
 
206
 */
 
207
static int com32_load_image ( struct image *image ) {
 
208
        size_t filesz, memsz;
 
209
        userptr_t buffer;
 
210
        int rc;
 
211
 
 
212
        filesz = image->len;
 
213
        memsz = filesz;
 
214
        buffer = phys_to_user ( COM32_START_PHYS );
 
215
        if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
 
216
                DBGC ( image, "COM32 %p: could not prepare segment: %s\n",
 
217
                       image, strerror ( rc ) );
 
218
                return rc;
 
219
        }
 
220
 
 
221
        /* Copy image to segment */
 
222
        memcpy_user ( buffer, 0, image->data, 0, filesz );
 
223
 
 
224
        return 0;
 
225
}
 
226
 
 
227
/**
 
228
 * Prepare COM32 low memory bounce buffer
 
229
 * @v image             COM32 image
 
230
 * @ret rc              Return status code
 
231
 */
 
232
static int com32_prepare_bounce_buffer ( struct image * image ) {
 
233
        unsigned int seg;
 
234
        userptr_t seg_userptr;
 
235
        size_t filesz, memsz;
 
236
        int rc;
 
237
 
 
238
        seg = COM32_BOUNCE_SEG;
 
239
        seg_userptr = real_to_user ( seg, 0 );
 
240
 
 
241
        /* Ensure the entire 64k segment is free */
 
242
        memsz = 0xFFFF;
 
243
        filesz = 0;
 
244
 
 
245
        /* Prepare, verify, and load the real-mode segment */
 
246
        if ( ( rc = prep_segment ( seg_userptr, filesz, memsz ) ) != 0 ) {
 
247
                DBGC ( image, "COM32 %p: could not prepare bounce buffer segment: %s\n",
 
248
                       image, strerror ( rc ) );
 
249
                return rc;
 
250
        }
 
251
 
 
252
        return 0;
 
253
}
 
254
 
 
255
/**
 
256
 * Probe COM32 image
 
257
 *
 
258
 * @v image             COM32 image
 
259
 * @ret rc              Return status code
 
260
 */
 
261
static int com32_probe ( struct image *image ) {
 
262
        int rc;
 
263
 
 
264
        DBGC ( image, "COM32 %p: name '%s'\n", image, image->name );
 
265
 
 
266
        /* Check if this is a COMBOOT image */
 
267
        if ( ( rc = com32_identify ( image ) ) != 0 ) {
 
268
                return rc;
 
269
        }
 
270
 
 
271
        return 0;
 
272
}
 
273
 
 
274
/**
 
275
 * Execute COMBOOT image
 
276
 *
 
277
 * @v image             COM32 image
 
278
 * @ret rc              Return status code
 
279
 */
 
280
static int com32_exec ( struct image *image ) {
 
281
        int rc;
 
282
 
 
283
        /* Load image */
 
284
        if ( ( rc = com32_load_image ( image ) ) != 0 ) {
 
285
                return rc;
 
286
        }
 
287
 
 
288
        /* Prepare bounce buffer segment */
 
289
        if ( ( rc = com32_prepare_bounce_buffer ( image ) ) != 0 ) {
 
290
                return rc;
 
291
        }
 
292
 
 
293
        /* Reset console */
 
294
        console_reset();
 
295
 
 
296
        return com32_exec_loop ( image );
 
297
}
 
298
 
 
299
/** SYSLINUX COM32 image type */
 
300
struct image_type com32_image_type __image_type ( PROBE_NORMAL ) = {
 
301
        .name = "COM32",
 
302
        .probe = com32_probe,
 
303
        .exec = com32_exec,
 
304
};