source: bootcd/isolinux/syslinux-6.03/com32/elflink/ldlinux/loadhigh.c

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

bootstuff

  • Property mode set to 100644
File size: 2.9 KB
RevLine 
[e16e8f2]1/*
2 * -----------------------------------------------------------------------
3 *
4 *   Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
5 *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
6 *
7 *   This program is free software; you can redistribute it and/or modify
8 *   it under the terms of the GNU General Public License as published by
9 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
10 *   Boston MA 02111-1307, USA; either version 2 of the License, or
11 *   (at your option) any later version; incorporated herein by reference.
12 *
13 * ----------------------------------------------------------------------- */
14
15/*
16 * loadhigh.c
17 *
18 * An alternate interface to getfssec.
19 *
20 * Inputs:      SI  = file handle/cluster pointer
21 *              EDI = target address in high memory
22 *              EAX = maximum number of bytes to load
23 *              DX  = zero-padding mask (e.g. 0003h for pad to dword)
24 *              BX  = 16-bit subroutine to call at the top of each loop
25 *                    (to print status and check for abort)
26 *              EBP = maximum load address
27 *
28 * Outputs:     SI  = file handle/cluster pointer
29 *              EBX = first untouched address (not including padding)
30 *              EDI = first untouched address (including padding)
31 *              CF  = reached EOF
32 *              OF  = ran out of high memory
33 */
34
35#include <com32.h>
36#include <minmax.h>
37#include "core.h"
38#include "fs.h"
39
40#define MAX_CHUNK       (1UL << 20) /* 1 MB */
41
42void pm_load_high(com32sys_t *regs)
43{
44    struct fs_info *fs;
45    uint32_t bytes;
46    uint32_t zero_mask;
47    bool have_more;
48    uint32_t bytes_read;
49    char *buf, *limit;
50    struct file *file;
51    uint32_t sector_mask;
52    size_t pad;
53    uint32_t retflags = 0;
54
55    bytes     = regs->eax.l;
56    zero_mask = regs->edx.w[0];
57    buf       = (char *)regs->edi.l;
58    limit     = (char *)(regs->ebp.l & ~zero_mask);
59    file      = handle_to_file(regs->esi.w[0]);
60    fs        = file->fs;
61
62    sector_mask = SECTOR_SIZE(fs) - 1;
63
64    while (bytes) {
65        uint32_t sectors;
66        uint32_t chunk;
67
68        if (buf + SECTOR_SIZE(fs) > limit) {
69            /* Can't fit even one more sector in... */
70            retflags = EFLAGS_OF;
71            break;
72        }
73
74        chunk = bytes;
75
76        if (regs->ebx.w[0]) {
77            call16((void (*)(void))(size_t)regs->ebx.w[0], &zero_regs, NULL);
78            chunk = min(chunk, MAX_CHUNK);
79        }
80
81        if (chunk > (((char *)limit - buf) & ~sector_mask))
82            chunk = ((char *)limit - buf) & ~sector_mask;
83
84        sectors = (chunk + sector_mask) >> SECTOR_SHIFT(fs);
85        bytes_read = fs->fs_ops->getfssec(file, buf, sectors, &have_more);
86
87        if (bytes_read > chunk)
88            bytes_read = chunk;
89
90        buf += bytes_read;
91        bytes -= bytes_read;
92
93        if (!have_more) {
94            /*
95             * If we reach EOF, the filesystem driver will have already closed
96             * the underlying file... this really should be cleaner.
97             */
98            _close_file(file);
99            regs->esi.w[0] = 0;
100            retflags = EFLAGS_CF;
101            break;
102        }
103    }
104
105    pad = (size_t)buf & zero_mask;
106    if (pad)
107        memset(buf, 0, pad);
108
109    regs->ebx.l = (size_t)buf;
110    regs->edi.l = (size_t)buf + pad;
111    set_flags(regs, retflags);
112}
Note: See TracBrowser for help on using the repository browser.