Ejemplo n.º 1
0
int is_no_emulation(int drive)
{
	struct packet
	{
		unsigned char packet_size;
		unsigned char media_type;
		unsigned char drive_num;
		unsigned char ctrlr_index;
		unsigned long lba;
		unsigned short device_spec;
		unsigned short buffer_segment;
		unsigned short load_segment;
		unsigned short sector_count;
		unsigned char cyl_count;
		unsigned char sec_count;
		unsigned char head_count;
		unsigned char reseved;
	} __attribute__((packed));
	static struct packet pkt;

	bzero(&pkt, sizeof(pkt));
	pkt.packet_size = 0x13;

	bb.intno   = 0x13;
	bb.eax.r.h = 0x4b;
	bb.eax.r.l = 0x01;     // subfunc: get info
	bb.edx.r.l = drive;
	bb.esi.rr = NORMALIZED_OFFSET((unsigned)&pkt);
	bb.ds     = NORMALIZED_SEGMENT((unsigned)&pkt);

	bios(&bb);

#if DEBUG
	printf("el_torito info drive %x\n", drive);
	printf("--> cf %x, eax %x\n", bb.flags.cf, bb.eax.rr);
	printf("pkt_size: %x\n", pkt.packet_size);
	printf("media_type: %x\n", pkt.media_type);
	printf("drive_num: %x\n", pkt.drive_num);
	printf("device_spec: %x\n", pkt.device_spec);
	printf("press a key->\n");
	getchar();
#endif

	/* Some BIOSes erroneously return cf = 1 */
	/* Just check to see if the drive number is the same. */
	if (pkt.drive_num == drive && (pkt.media_type & 0x0F) == 0)
	{
		return 1; // We are in no-emulation mode.
	}

	return 0;
}
Ejemplo n.º 2
0
int get_drive_info(int drive, struct driveInfo *dp)
{
    boot_drive_info_t *di = &dp->di;
    int ret = 0;

#if UNUSED
    if (maxhd == 0)
    {
        bb.intno = 0x13;
        bb.eax.r.h = 0x08;
        bb.edx.r.l = 0x80;
        bios(&bb);

        if (bb.flags.cf == 0)
            maxhd = 0x7f + bb.edx.r.l;
    };

    if (drive > maxhd)
        return 0;
#endif

    bzero(dp, sizeof(struct driveInfo));
    dp->biosdev = drive;

    /* Check for El Torito no-emulation mode. */
    dp->no_emulation = is_no_emulation(drive);

    /* Check drive for EBIOS support. */
    bb.intno = 0x13;
    bb.eax.r.h = 0x41;
    bb.edx.r.l = drive;
    bb.ebx.rr = 0x55aa;
    bios(&bb);

    if ((bb.ebx.rr == 0xaa55) && (bb.flags.cf == 0))
        dp->uses_ebios = bb.ecx.r.l; // Get flags for supported operations.

    if (dp->uses_ebios & (EBIOS_ENHANCED_DRIVE_INFO | EBIOS_LOCKING_ACCESS | EBIOS_FIXED_DISK_ACCESS))
    {
        // Get EBIOS drive info.
        static struct drive_params params;
        params.buf_size = sizeof(params);
        bb.intno = 0x13;
        bb.eax.r.h = 0x48;
        bb.edx.r.l = drive;
        bb.esi.rr = NORMALIZED_OFFSET((unsigned)&params);
        bb.ds     = NORMALIZED_SEGMENT((unsigned)&params);
        bios(&bb);

        if (bb.flags.cf != 0 /* || params.phys_sectors < 2097152 */)
        {
            dp->uses_ebios = 0;
            di->params.buf_size = 1;
        }
        else
        {
            bcopy(&params, &di->params, sizeof(params));

            if (drive >= BASE_HD_DRIVE && 
                (dp->uses_ebios & EBIOS_ENHANCED_DRIVE_INFO) &&
                di->params.buf_size >= 30 &&
                !(di->params.dpte_offset == 0xFFFF && di->params.dpte_segment == 0xFFFF))
            {
                void *ptr = (void *)(di->params.dpte_offset + ((unsigned int)di->params.dpte_segment << 4));
                bcopy(ptr, &di->dpte, sizeof(di->dpte));
            }
        }
    }

    if (dp->no_emulation)
    {
        /* Some BIOSes give us erroneous EBIOS support information.
         * Assume that if you're on a CD, then you can use
         * EBIOS disk calls.
         */
        dp->uses_ebios |= EBIOS_FIXED_DISK_ACCESS;
    }
#if DEBUG
    print_drive_info(di);
    printf("uses_ebios = 0x%x\n", dp->uses_ebios);
    printf("result %d\n", ret);
    printf("press a key->\n");getc();
#endif

    if (ret == 0)
        dp->valid = 1;

    return ret;
}
Ejemplo n.º 3
0
int ebiosread(int dev, unsigned long long sec, int count)
{
	int i;
    
	static struct
	{
		unsigned char  size;
		unsigned char  reserved;
		unsigned char  numblocks;
		unsigned char  reserved2;
		unsigned short bufferOffset;
		unsigned short bufferSegment;
		unsigned long  long startblock;
	} addrpacket __attribute__((aligned(16))) = {0};
	addrpacket.size = sizeof(addrpacket);

	for (i = 0; ;)
	{
		bb.intno   = 0x13;
		bb.eax.r.h = 0x42;
		bb.edx.r.l = dev;
		bb.esi.rr  = NORMALIZED_OFFSET((unsigned)&addrpacket);
		bb.ds      = NORMALIZED_SEGMENT((unsigned)&addrpacket);
		addrpacket.reserved = addrpacket.reserved2 = 0;
		addrpacket.numblocks     = count;
		addrpacket.bufferOffset  = OFFSET(ptov(BIOS_ADDR));
		addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR));
		addrpacket.startblock    = sec;
		bios(&bb);

		// In case of a successful call, make sure we set AH (return code) to zero.
		if (bb.flags.cf == 0)
		{
			bb.eax.r.h = 0;
		}
		
		// Now we can really check for the return code (AH) value.
		if ((bb.eax.r.h == 0x00) || (i++ >= 5))
		{
			break;
		}

        // Reset disk subsystem and try again.
		bb.eax.r.h = 0x00;
		bios(&bb);
	}

	return bb.eax.r.h;
}


//==============================================================================

void putc(int ch)
{
	bb.intno = 0x10;
	bb.ebx.r.h = 0x00;  /* background black */
	bb.ebx.r.l = 0x0F;  /* foreground white */
	bb.eax.r.h = 0x0e;
	bb.eax.r.l = ch;
	bios(&bb);
}
Ejemplo n.º 4
0
unsigned long getMemoryMap(MemoryRange * rangeArray, unsigned long maxRangeCount, unsigned long * conMemSizePtr, unsigned long * extMemSizePtr)
{
	#define kMemoryMapSignature  'SMAP'
	#define kDescriptorSizeMin   20

	MemoryRange *        range = (MemoryRange *)BIOS_ADDR;
	unsigned long        count = 0;
	unsigned long long   conMemSize = 0;
	unsigned long long   extMemSize = 0;

    // Prepare for the INT15 E820h call. Each call returns a single
    // memory range. A continuation value is returned that must be
    // provided on a subsequent call to fetch the next range.
    //
    // Certain BIOSes (Award 6.00PG) expect the upper word in EAX
    // to be cleared on entry, otherwise only a single range will
    // be reported.
    //
    // Some BIOSes will simply ignore the value of ECX on entry.
    // Probably best to keep its value at 20 to avoid surprises.

    //printf("Get memory map 0x%x, %d\n", rangeArray);getc();
    if (maxRangeCount > (BIOS_LEN / sizeof(MemoryRange)))
        maxRangeCount = (BIOS_LEN / sizeof(MemoryRange));

    bb.ebx.rx = 0;  // Initial continuation value must be zero.

    while (count < maxRangeCount)
    {
        bb.intno  = 0x15;
        bb.eax.rx = 0xe820;
        bb.ecx.rx = kDescriptorSizeMin;
        bb.edx.rx = kMemoryMapSignature;
        bb.edi.rr = NORMALIZED_OFFSET(  (unsigned long) range );
        bb.es     = NORMALIZED_SEGMENT( (unsigned long) range );
        bios(&bb);

        // Check for errors.

        if ( bb.flags.cf ||   bb.eax.rx != kMemoryMapSignature
            || bb.ecx.rx != kDescriptorSizeMin )
        {
            //printf("Got an error %x %x %x\n", bb.flags.cf,
            //       bb.eax.rx, bb.ecx.rx);
            break;
        }

        // Tally up the conventional/extended memory sizes.

        if (range->type == kMemoryRangeUsable || range->type == kMemoryRangeACPI   ||
            range->type == kMemoryRangeNVS )
        {
            // Tally the conventional memory ranges.
            if (range->base + range->length <= 0xa0000)
                conMemSize += range->length;

            // Record the top of extended memory.
            if (range->base >= EXTENDED_ADDR)
                extMemSize += range->length;
        }

        range++;
        count++;

        // Is this the last address range?

        if ( bb.ebx.rx == 0 ) {
            //printf("last range\n");
            break;
        }
    }
    *conMemSizePtr = conMemSize / 1024;  // size in KB
    *extMemSizePtr = extMemSize / 1024;  // size in KB

    // Copy out data
    bcopy((char *)BIOS_ADDR, rangeArray, ((char *)range - (char *)BIOS_ADDR));

#if DEBUG
    {
        int i;
        printf("%d total ranges\n", count);getc();

        for (i=0, range = rangeArray; i<count; i++, range++)
        {
            printf("range: type %d, base 0x%x, length 0x%x\n",
                   range->type, (unsigned int)range->base, (unsigned int)range->length);
            getc();
        }
    }
#endif

    return count;
}