Added BIOS drive mapping functionality

svn path=/trunk/; revision=3284
This commit is contained in:
Brian Palmer 2002-07-22 03:44:08 +00:00
parent c747481470
commit 1aa76f94bd
15 changed files with 525 additions and 100 deletions

View file

@ -53,6 +53,7 @@
; BootType - sets the boot type: ReactOS, Linux, BootSector, Partition, Drive ; BootType - sets the boot type: ReactOS, Linux, BootSector, Partition, Drive
; BootDrive - sets the boot drive: 0 - first floppy, 1 - second floppy, 0x80 - first hard disk, 0x81 - second hard disk ; BootDrive - sets the boot drive: 0 - first floppy, 1 - second floppy, 0x80 - first hard disk, 0x81 - second hard disk
; BootPartition - sets the boot partition ; BootPartition - sets the boot partition
; DriveMap - maps a BIOS drive number to another (i.e. DriveMap=hd1,hd0 maps harddisk1 to harddisk0 or DriveMap=fd1,fd0)
; [BootSector OSType] Section Commands: ; [BootSector OSType] Section Commands:
; ;

View file

@ -1,7 +1,10 @@
Changes in v1.6 (7/21/2002) (brianp)
- Added BIOS drive mapping functionality
Changes in v1.5 (7/13/2002) Changes in v1.5 (7/13/2002)
- If symbols are available then pass them to the OS as multiboot modules - If symbols are available then pass them to the OS as multiboot modules
- Added separate configuration for a SETUPLDR version
Changes in v1.4 (6/27/2002) Changes in v1.4 (6/27/2002)

View file

@ -112,7 +112,8 @@ else
############################################# #############################################
# COMPILER COMMAND LINE OPTIONS # COMPILER COMMAND LINE OPTIONS
# #
COMPILER_OPTIONS = -Wall -nostdlib -fno-builtin -O1 -MD COMPILER_OPTIONS = -Wall -nostdlib -nostdinc -fno-builtin -O1 -MD
# FreeLoader does not use any of the standard libraries, includes, or built-in functions
############################################# #############################################
# COMPILER DEFINES # COMPILER DEFINES
@ -180,9 +181,10 @@ ARCH_OBJS = fathelp.o \
linux.o \ linux.o \
mb.o \ mb.o \
mem.o \ mem.o \
diskint13.o \ biosdisk.o \
rtlcode.o \ rtlcode.o \
biosvid.o biosvid.o \
drvmap.o
RTL_OBJS = memory.o \ RTL_OBJS = memory.o \
print.o \ print.o \
@ -234,6 +236,7 @@ FREELDR_OBJS= freeldr.o \
debug.o \ debug.o \
oslist.o \ oslist.o \
bootmgr.o \ bootmgr.o \
drivemap.o \
version.o version.o
############################################# #############################################

View file

@ -0,0 +1,132 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
.text
.code16
#define ASM
#include <arch.h>
EXTERN(_DriveMapInt13HandlerStart)
Int13Handler:
pushw %bp
movw %sp,%bp
pushw %ax
pushw %cx
pushw %si
cld
/* Get callers flags from stack */
movw 0x06(%bp),%ax
movw %ax,%cs:(CallersFlags - Int13Handler)
/* Save the drive number they passed in */
movb %dl,%cs:(PassedInDriveNumber - Int13Handler)
/* Now we need to perform the mapping */
xorw %cx,%cx
movw $(Int13HandlerMapCount - Int13Handler),%si
/* Get the count of drives in the map list */
movb %cs:(%si),%cl
incw %si
/* If the map list is empty then just call the old int 13h handler */
cmpb $0,%cl
jz CallOldInt13Handler
GetMappedDriveNumberLoop:
/* Get the next drive number in the list */
lodsw %cs:(%si),%ax
/* Check to see if it's the one they are calling int 13h for */
cmpb %al,%dl
/* If not get the next one */
jne GetMappedDriveNumberLoopNext
/* If we get here then we have found a mapped drive */
/* Send new drive number on to the old int 13h handler */
movb %ah,%dl
/* Call BIOS Int 13 Handler */
jmp CallOldInt13Handler
GetMappedDriveNumberLoopNext:
loop GetMappedDriveNumberLoop
CallOldInt13Handler:
/* Restore the registers we changed off the stack */
popw %si
popw %cx
popw %ax
/* Put flags onto stack */
pushw %cs:(CallersFlags - Int13Handler)
/* Call old int 13h handler with new drive number */
.byte 0x9a /* lcall */
EXTERN(_DriveMapOldInt13HandlerAddress)
.word 0
.word 0
/* Update the callers flags with the values the BIOS returned */
pushw %ax
pushf
popw %ax
movw %ax,0x06(%bp)
popw %ax
/* Restore the callers drive number */
movb %cs:(PassedInDriveNumber - Int13Handler),%dl
popw %bp
iret
CallersFlags:
.word 0
PassedInDriveNumber:
.byte 0
EXTERN(_DriveMapInt13HandlerMapList)
Int13HandlerMapCount:
.byte 0
Int13HandlerDrive1:
.byte 0
Int13HandlerDriveNew1:
.byte 0
Int13HandlerDrive2:
.byte 0
Int13HandlerDriveNew2:
.byte 0
Int13HandlerDrive3:
.byte 0
Int13HandlerDriveNew3:
.byte 0
Int13HandlerDrive4:
.byte 0
Int13HandlerDriveNew4:
.byte 0
EXTERN(_DriveMapInt13HandlerEnd)

View file

@ -31,6 +31,7 @@
#include <oslist.h> #include <oslist.h>
#include <video.h> #include <video.h>
#include <bootmgr.h> #include <bootmgr.h>
#include <drivemap.h>
VOID RunBootManager(VOID) VOID RunBootManager(VOID)
{ {
@ -115,6 +116,9 @@ VOID RunBootManager(VOID)
continue; continue;
} }
// Install the drive mapper according to this sections drive mappings
DriveMapMapDrivesInSection(OperatingSystemSectionNames[SelectedOperatingSystem]);
if (stricmp(SettingValue, "ReactOS") == 0) if (stricmp(SettingValue, "ReactOS") == 0)
{ {
LoadAndBootReactOS(OperatingSystemSectionNames[SelectedOperatingSystem]); LoadAndBootReactOS(OperatingSystemSectionNames[SelectedOperatingSystem]);

View file

@ -32,6 +32,7 @@
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
CACHE_DRIVE CacheManagerDrive; CACHE_DRIVE CacheManagerDrive;
BOOL CacheManagerInitialized = FALSE; BOOL CacheManagerInitialized = FALSE;
BOOL CacheManagerDataInvalid = FALSE;
ULONG CacheBlockCount = 0; ULONG CacheBlockCount = 0;
ULONG CacheSizeLimit = 0; ULONG CacheSizeLimit = 0;
ULONG CacheSizeCurrent = 0; ULONG CacheSizeCurrent = 0;
@ -45,11 +46,14 @@ BOOL CacheInitializeDrive(ULONG DriveNumber)
// drive, in which case we'll invalidate the cache // drive, in which case we'll invalidate the cache
if ((CacheManagerInitialized == TRUE) && if ((CacheManagerInitialized == TRUE) &&
(DriveNumber == CacheManagerDrive.DriveNumber) && (DriveNumber == CacheManagerDrive.DriveNumber) &&
(DriveNumber >= 0x80)) (DriveNumber >= 0x80) &&
(CacheManagerDataInvalid != TRUE))
{ {
return TRUE; return TRUE;
} }
CacheManagerDataInvalid = FALSE;
// //
// If we have already been initialized then free // If we have already been initialized then free
// the old data // the old data
@ -120,6 +124,11 @@ BOOL CacheInitializeDrive(ULONG DriveNumber)
return TRUE; return TRUE;
} }
VOID CacheInvalidateCacheData(VOID)
{
CacheManagerDataInvalid = TRUE;
}
BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer) BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer)
{ {
PCACHE_BLOCK CacheBlock; PCACHE_BLOCK CacheBlock;

View file

@ -27,28 +27,20 @@
//#define DEBUG_ULTRA //#define DEBUG_ULTRA
//#define DEBUG_INIFILE //#define DEBUG_INIFILE
//#define DEBUG_REACTOS //#define DEBUG_REACTOS
//#define DEBUG_CUSTOM #define DEBUG_CUSTOM
#define DEBUG_NONE //#define DEBUG_NONE
#ifdef DEBUG_ULTRA #if defined (DEBUG_ULTRA)
ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM |
DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS | DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS |
DPRINT_LINUX; DPRINT_LINUX;
#endif #elif defined (DEBUG_INIFILE)
#ifdef DEBUG_INIFILE
ULONG DebugPrintMask = DPRINT_INIFILE; ULONG DebugPrintMask = DPRINT_INIFILE;
#endif #elif defined (DEBUG_REACTOS)
#ifdef DEBUG_REACTOS
ULONG DebugPrintMask = DPRINT_REACTOS | DPRINT_REGISTRY; ULONG DebugPrintMask = DPRINT_REACTOS | DPRINT_REGISTRY;
#endif #elif defined (DEBUG_CUSTOM)
ULONG DebugPrintMask = DPRINT_WARNING;
#ifdef DEBUG_CUSTOM #else //#elif defined (DEBUG_NONE)
ULONG DebugPrintMask = 0;
#endif
#ifdef DEBUG_NONE
ULONG DebugPrintMask = 0; ULONG DebugPrintMask = 0;
#endif #endif
@ -253,7 +245,13 @@ VOID DebugPrint(ULONG Mask, char *format, ...)
} }
else else
{ {
switch (c = *(format++)) c = *(format++);
if (c == 'l')
{
c = *(format++);
}
switch (c)
{ {
case 'd': case 'u': case 'x': case 'd': case 'u': case 'x':

219
freeldr/freeldr/drivemap.c Normal file
View file

@ -0,0 +1,219 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <freeldr.h>
#include <drivemap.h>
#include <rtl.h>
#include <inifile.h>
#include <cache.h>
#include <ui.h>
#include <debug.h>
BOOL DriveMapInstalled = FALSE; // Tells us if we have already installed our drive map int 13h handler code
ULONG OldInt13HandlerAddress = 0; // Address of BIOS int 13h handler
ULONG DriveMapHandlerAddress = 0; // Linear address of our drive map handler
ULONG DriveMapHandlerSegOff = 0; // Segment:offset style address of our drive map handler
VOID DriveMapMapDrivesInSection(PUCHAR SectionName)
{
UCHAR SettingName[80];
UCHAR SettingValue[80];
UCHAR ErrorText[260];
UCHAR Drive1[80];
UCHAR Drive2[80];
ULONG SectionId;
ULONG SectionItemCount;
ULONG Index;
ULONG Index2;
DRIVE_MAP_LIST DriveMapList;
RtlZeroMemory(&DriveMapList, sizeof(DRIVE_MAP_LIST));
if (!IniOpenSection(SectionName, &SectionId))
{
return;
}
// Get the number of items in this section
SectionItemCount = IniGetNumSectionItems(SectionId);
// Loop through each one and check if its a DriveMap= setting
for (Index=0; Index<SectionItemCount; Index++)
{
// Get the next setting from the .ini file section
if (IniReadSettingByNumber(SectionId, Index, SettingName, 80, SettingValue, 80))
{
if (stricmp(SettingName, "DriveMap") == 0)
{
// Make sure we haven't exceeded the drive map max count
if (DriveMapList.DriveMapCount >= 4)
{
sprintf(ErrorText, "Max DriveMap count exceeded in section [%s]:\n\n%s=%s", SectionName, SettingName, SettingValue);
UiMessageBox(ErrorText);
continue;
}
RtlZeroMemory(Drive1, 80);
RtlZeroMemory(Drive2, 80);
strcpy(Drive1, SettingValue);
// Parse the setting value and separate a string "hd0,hd1"
// into two strings "hd0" and "hd1"
for (Index2=0; Index2<strlen(Drive1); Index2++)
{
// Check if this character is the separater character (comma - ',')
if (Drive1[Index2] == ',')
{
Drive1[Index2] = '\0';
strcpy(Drive2, &Drive1[Index2+1]);
break;
}
}
// Make sure we got good values before we add them to the map
if (!DriveMapIsValidDriveString(Drive1) || !DriveMapIsValidDriveString(Drive2))
{
sprintf(ErrorText, "Error in DriveMap setting in section [%s]:\n\n%s=%s", SectionName, SettingName, SettingValue);
UiMessageBox(ErrorText);
continue;
}
// Add them to the map
DriveMapList.DriveMap[(DriveMapList.DriveMapCount * 2)] = DriveMapGetBiosDriveNumber(Drive1);
DriveMapList.DriveMap[(DriveMapList.DriveMapCount * 2)+1] = DriveMapGetBiosDriveNumber(Drive2);
DriveMapList.DriveMapCount++;
DbgPrint((DPRINT_WARNING, "Mapping BIOS drive 0x%x to drive 0x%x\n", DriveMapGetBiosDriveNumber(Drive1), DriveMapGetBiosDriveNumber(Drive2)));
}
}
}
if (DriveMapList.DriveMapCount)
{
DbgPrint((DPRINT_WARNING, "Installing Int13 drive map for %d drives.\n", DriveMapList.DriveMapCount));
DriveMapInstallInt13Handler(&DriveMapList);
}
else
{
DbgPrint((DPRINT_WARNING, "Removing any previously installed Int13 drive map.\n"));
DriveMapRemoveInt13Handler();
}
}
BOOL DriveMapIsValidDriveString(PUCHAR DriveString)
{
ULONG Index;
// Now verify that the user has given us appropriate strings
if ((strlen(DriveString) < 3) ||
((DriveString[0] != 'f') && (DriveString[0] != 'F') && (DriveString[0] != 'h') && (DriveString[0] != 'H')) ||
((DriveString[1] != 'd') && (DriveString[1] != 'D')))
{
return FALSE;
}
// Now verify that the user has given us appropriate numbers
// Make sure that only numeric characters were given
for (Index=2; Index<strlen(DriveString); Index++)
{
if (DriveString[Index] < '0' || DriveString[Index] > '9')
{
return FALSE;
}
}
// Now make sure that they are not outrageous values (i.e. hd90874)
if ((atoi(&DriveString[2]) < 0) || (atoi(&DriveString[2]) > 0xff))
{
return FALSE;
}
return TRUE;
}
ULONG DriveMapGetBiosDriveNumber(PUCHAR DeviceName)
{
ULONG BiosDriveNumber = 0;
// Convert the drive number string into a number
// 'hd1' = 1
BiosDriveNumber = atoi(&DeviceName[2]);
// If it's a hard disk then set the high bit
if ((DeviceName[0] == 'h' || DeviceName[0] == 'H') &&
(DeviceName[1] == 'd' || DeviceName[1] == 'D'))
{
BiosDriveNumber |= 0x80;
}
return BiosDriveNumber;
}
VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap)
{
PDWORD RealModeIVT = (PULONG)0x00000000;
PWORD BiosLowMemorySize = (PWORD)0x00000413;
if (!DriveMapInstalled)
{
// Get the old INT 13h handler address from the vector table
OldInt13HandlerAddress = RealModeIVT[0x13];
// Decrease the size of low memory
(*BiosLowMemorySize)--;
// Get linear address for drive map handler
DriveMapHandlerAddress = (ULONG)(*BiosLowMemorySize) << 10;
// Convert to segment:offset style address
DriveMapHandlerSegOff = (DriveMapHandlerAddress << 12) & 0xffff0000;
}
// Copy the drive map structure to the proper place
RtlCopyMemory(&DriveMapInt13HandlerMapList, DriveMap, sizeof(DRIVE_MAP_LIST));
// Set the address of the BIOS INT 13h handler
DriveMapOldInt13HandlerAddress = OldInt13HandlerAddress;
// Copy the code to our reserved area
RtlCopyMemory((PVOID)DriveMapHandlerAddress, &DriveMapInt13HandlerStart, ((ULONG)&DriveMapInt13HandlerEnd - (ULONG)&DriveMapInt13HandlerStart));
// Update the IVT
RealModeIVT[0x13] = DriveMapHandlerSegOff;
//CacheInvalidateCacheData();
DriveMapInstalled = TRUE;
}
VOID DriveMapRemoveInt13Handler(VOID)
{
PDWORD RealModeIVT = (PULONG)0x00000000;
PWORD BiosLowMemorySize = (PWORD)0x00000413;
if (DriveMapInstalled)
{
// Get the old INT 13h handler address from the vector table
RealModeIVT[0x13] = OldInt13HandlerAddress;
// Increase the size of low memory
(*BiosLowMemorySize)++;
DriveMapInstalled = FALSE;
}
}

View file

@ -19,17 +19,9 @@
#include <freeldr.h> #include <freeldr.h>
#include <rtl.h> #include <rtl.h>
#include <fs.h>
#include <reactos.h>
#include <ui.h>
#include <arch.h> #include <arch.h>
#include <miscboot.h>
#include <linux.h>
#include <mm.h> #include <mm.h>
#include <inifile.h>
#include <debug.h> #include <debug.h>
#include <oslist.h>
#include <video.h>
#include <bootmgr.h> #include <bootmgr.h>
// Variable BootDrive moved to asmcode.S // Variable BootDrive moved to asmcode.S

View file

@ -22,6 +22,7 @@
#define __CACHE_H #define __CACHE_H
BOOL CacheInitializeDrive(ULONG DriveNumber); BOOL CacheInitializeDrive(ULONG DriveNumber);
VOID CacheInvalidateCacheData(VOID);
BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer); BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer);
BOOL CacheForceDiskSectorsIntoCache(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount); BOOL CacheForceDiskSectorsIntoCache(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount);
BOOL CacheReleaseMemory(ULONG MinimumAmountToRelease); BOOL CacheReleaseMemory(ULONG MinimumAmountToRelease);

View file

@ -0,0 +1,43 @@
/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __DRIVEMAP_H
#define __DRIVEMAP_H
typedef struct
{
BYTE DriveMapCount; // Count of drives currently mapped
BYTE DriveMap[8]; // Map of BIOS drives
} PACKED DRIVE_MAP_LIST, *PDRIVE_MAP_LIST;
VOID DriveMapMapDrivesInSection(PUCHAR SectionName);
BOOL DriveMapIsValidDriveString(PUCHAR DriveString); // Checks the drive string ("hd0") for validity
ULONG DriveMapGetBiosDriveNumber(PUCHAR DeviceName); // Returns a BIOS drive number for any given device name (e.g. 0x80 for 'hd0')
VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap); // Installs the int 13h handler for the drive mapper
VOID DriveMapRemoveInt13Handler(VOID); // Removes a previously installed int 13h drive map handler
extern PVOID DriveMapInt13HandlerStart;
extern PVOID DriveMapInt13HandlerEnd;
extern ULONG DriveMapOldInt13HandlerAddress;
extern DRIVE_MAP_LIST DriveMapInt13HandlerMapList;
#endif // #defined __DRIVEMAP_H

View file

@ -22,7 +22,7 @@
/* just some stuff */ /* just some stuff */
#define VERSION "FreeLoader v1.5" #define VERSION "FreeLoader v1.6"
#define COPYRIGHT "Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>" #define COPYRIGHT "Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>"
#define AUTHOR_EMAIL "<brianp@sginet.com>" #define AUTHOR_EMAIL "<brianp@sginet.com>"
#define BY_AUTHOR "by Brian Palmer" #define BY_AUTHOR "by Brian Palmer"
@ -35,7 +35,7 @@
// If you add major functionality then you increment the major version and zero the minor & patch versions // If you add major functionality then you increment the major version and zero the minor & patch versions
// //
#define FREELOADER_MAJOR_VERSION 1 #define FREELOADER_MAJOR_VERSION 1
#define FREELOADER_MINOR_VERSION 5 #define FREELOADER_MINOR_VERSION 6
#define FREELOADER_PATCH_VERSION 0 #define FREELOADER_PATCH_VERSION 0

View file

@ -112,7 +112,7 @@ BOOL MmInitializeMemoryManager(VOID)
if (PageLookupTableAddress == 0) if (PageLookupTableAddress == 0)
{ {
// If we get here then we probably couldn't // If we get here then we probably couldn't
// find a contigous chunk of memory big // find a contiguous chunk of memory big
// enough to hold the page lookup table // enough to hold the page lookup table
printf("Error initializing memory manager!\n"); printf("Error initializing memory manager!\n");
return FALSE; return FALSE;

View file

@ -32,90 +32,110 @@ void print(char *str)
/* /*
* printf() - prints formatted text to stdout * printf() - prints formatted text to stdout
* from: * originally from GRUB
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1996 Erich Boleyn <erich@uruk.org>
*/ */
void printf(char *format, ... ) void printf(char *format, ... )
{ {
int *dataptr = (int *) &format; int *dataptr = (int *) &format;
char c, *ptr, str[16]; char c, *ptr, str[16];
dataptr++; dataptr++;
while ((c = *(format++))) while ((c = *(format++)))
{ {
if (c != '%') if (c != '%')
putchar(c); {
else putchar(c);
switch (c = *(format++)) }
{ else
case 'd': case 'u': case 'x': {
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0; c = *(format++);
if (c == 'l')
{
c = *(format++);
}
ptr = str; switch (c)
{
case 'd': case 'u': case 'x':
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
while (*ptr) ptr = str;
putchar(*(ptr++));
break;
case 'c': putchar((*(dataptr++))&0xff); break; while (*ptr)
{
putchar(*(ptr++));
}
break;
case 's': case 'c': putchar((*(dataptr++))&0xff); break;
ptr = (char *)(*(dataptr++));
while ((c = *(ptr++))) case 's':
putchar(c); ptr = (char *)(*(dataptr++));
break;
} while ((c = *(ptr++)))
} {
putchar(c);
}
break;
}
}
}
} }
void sprintf(char *buffer, char *format, ... ) void sprintf(char *buffer, char *format, ... )
{ {
int *dataptr = (int *) &format; int *dataptr = (int *) &format;
char c, *ptr, str[16]; char c, *ptr, str[16];
char *p = buffer; char *p = buffer;
dataptr++; dataptr++;
while ((c = *(format++))) while ((c = *(format++)))
{ {
if (c != '%') if (c != '%')
{ {
*p = c; *p = c;
p++; p++;
} }
else else
switch (c = *(format++)) {
{ c = *(format++);
case 'd': case 'u': case 'x': if (c == 'l')
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0; {
c = *(format++);
}
ptr = str; switch (c)
{
case 'd': case 'u': case 'x':
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
while (*ptr) ptr = str;
{
*p = *(ptr++);
p++;
}
break;
case 'c': while (*ptr)
*p = (*(dataptr++))&0xff; {
p++; *p = *(ptr++);
break; p++;
}
break;
case 's': case 'c':
ptr = (char *)(*(dataptr++)); *p = (*(dataptr++))&0xff;
p++;
break;
while ((c = *(ptr++))) case 's':
{ ptr = (char *)(*(dataptr++));
*p = c;
p++; while ((c = *(ptr++)))
} {
break; *p = c;
} p++;
} }
*p=0; break;
}
}
}
*p=0;
} }