[syslinux] [Syslinux-GSoC] Exporting real-mode functions

H. Peter Anvin hpa at zytor.com
Tue Jun 2 07:38:16 PDT 2009


liu Aleaxander wrote:
> 
> well, I have to say it alos does not work.
> 

I looked at your code, and the problem is that you're not using the
bounce buffer.

void getoneblk(char *buf, __u32 block, int block_size)
{
        int sec_per_block = block_size / 512; /* 512==sector size */
        com32sys_t regs;

        regs.eax.l = block * sec_per_block;
        regs.ebp.l = sec_per_block;
        regs.es = SEG(buf);
        regs.ebx.w[0] = OFFS(buf);

        call16(getlinsec, &regs, NULL);
}

Here, "buf" will generally be > 1 MB, so applying SEG() and OFFS() to it
results in garbage.

Instead, you need to do something like:

void getoneblk(char *buf, __u32 block, int block_size)
{
        int sec_per_block = block_size / 512; /* 512==sector size */
        com32sys_t regs;

	/* We need to clear at least the segment registers... */
	memset(&regs, 0, sizeof regs);

        regs.eax.l = block * sec_per_block;
        regs.ebp.l = sec_per_block;
        regs.es = SEG(core_xfer_buf);
        regs.ebx.w[0] = OFFS(core_xfer_buf);	/* Or just zero */

        call16(getlinsec, &regs, NULL);

	memcpy(buf, core_xfer_buf, block_size);
}


Similarly, returning the pointer in gs:si doesn't work, since it's above
the 1 MB boundary.  We probably can't use core_xfer_buf to return the
block, though, so doing what you want to do here is nontrival -- the
easiest way to do this is to export the existing 16-bit cache_seg in the
same way we have xfer_buf_seg -> core_xfer_buf; that can then replace
cache_data[] until we have moved all the cache-using code to 32-bit
mode.  I just checked in such an export.


A few technical notes:

I believe the existing code will call getcachesec with a zero block
number; it expects to get back a cache pointer for a zeroed block.


A few stylistic notes:

- Please use shifts instead of multiplications and divisions.  This
often means keeping sizes as power of two rather than direct numbers
(i.e. block_size probably should be "12" instead of "4096").

- I'd prefer if we used <inttypes.h> types, i.e. uint32_t rather than __u32.

- Don't put prototypes inside functions.  However, if you are allocating
a static buffer which will only be used inside one function, *do* put it
inside the function.

	-hpa


-- 
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.




More information about the Syslinux mailing list