/*++ Copyright (c) 1991 Microsoft Corporation Module Name: parsboot.c Abstract: Parses the boot.ini file, displays a menu, and provides a kernel path and name to be passed to osloader. Author: John Vert (jvert) 22-Jul-1991 Revision History: --*/ #include "bldrx86.h" #include "msg.h" #include "ntdddisk.h" #include #include #include #define ENTER_KEY 0x0d #define MAX_SELECTIONS 10 #define MAX_TITLE_LENGTH 71 #define WIN95_DOS 1 #define DOS_WIN95 2 typedef struct _MENU_OPTION { PCHAR Title; PCHAR Path; BOOLEAN EnableDebug; ULONG MaxMemory; PCHAR LoadOptions; int ForcedScsiOrdinal; int Win95; } MENU_OPTION, *PMENU_OPTION; int ForcedScsiOrdinal = -1; // // Private function prototypes // VOID BlpRebootDOS( IN PCHAR BootSectorImage OPTIONAL ); PCHAR BlpNextLine( IN PCHAR String ); VOID BlpTranslateDosToArc( IN PCHAR DosName, OUT PCHAR ArcName ); VOID BlpTruncateMemory( IN ULONG MaxMemory ); ULONG BlpPresentMenu( IN PMENU_OPTION MenuOptions, IN ULONG NumberSelections, IN ULONG Default, IN LONG Timeout ); PCHAR * BlpFileToLines( IN PCHAR File, OUT PULONG LineCount ); PCHAR * BlpFindSection( IN PCHAR SectionName, IN PCHAR *BootFile, IN ULONG BootFileLines, OUT PULONG NumberLines ); VOID BlpRenameWin95Files( IN ULONG DriveId, IN ULONG Type ); PCHAR BlSelectKernel( IN ULONG DriveId, IN PCHAR BootFile, OUT PCHAR *LoadOptions, IN BOOLEAN UseTimeOut ) /*++ Routine Description: Parses the boot.txt file and determines the fully-qualified name of the kernel to be booted. Arguments: BootFile - Pointer to the beginning of the loaded boot.txt file Debugger - Returns the enable/disable state of the kernel debugger UseTimeOut - Supplies whether the boot menu should time out or not. Return Value: Pointer to the name of a kernel to boot. --*/ { PCHAR *MbLines; PCHAR *OsLines; PCHAR *FileLines; #if DBG PCHAR *DebugLines; ULONG DebugLineCount; #endif ULONG FileLineCount; ULONG OsLineCount; ULONG MbLineCount; PCHAR pCurrent; PCHAR Option; MENU_OPTION MenuOption[MAX_SELECTIONS+1]; ULONG NumberSystems=0; ULONG i; LONG Timeout; ULONG Selection; ULONG DefaultSelection=0; static CHAR Kernel[128]; CHAR DosName[3]; PCHAR DefaultPath="C:\\winnt\\"; PCHAR DefaultTitle="NT (default)"; PCHAR p; *LoadOptions = NULL; if (*BootFile == '\0') { // // No boot.ini file, so we boot the default. // BlPrint(BlFindMessage(BL_INVALID_BOOT_INI),DefaultPath); MenuOption[0].Path = DefaultPath; MenuOption[0].Title = DefaultTitle; MenuOption[0].MaxMemory = 0; MenuOption[0].LoadOptions = NULL; MenuOption[0].Win95 = 0; NumberSystems = 1; DefaultSelection = 0; MbLineCount = 0; OsLineCount = 0; MenuOption[0].EnableDebug = FALSE; #if DBG DebugLineCount = 0; #endif } else { FileLines = BlpFileToLines(BootFile, &FileLineCount); MbLines = BlpFindSection("[boot loader]", FileLines, FileLineCount, &MbLineCount); if (MbLines==NULL) { MbLines = BlpFindSection("[flexboot]", FileLines, FileLineCount, &MbLineCount); if (MbLines==NULL) { MbLines = BlpFindSection("[multiboot]", FileLines, FileLineCount, &MbLineCount); } } OsLines = BlpFindSection("[operating systems]", FileLines, FileLineCount, &OsLineCount); if (OsLineCount == 0) { BlPrint(BlFindMessage(BL_INVALID_BOOT_INI),DefaultPath); MenuOption[0].Path = DefaultPath; MenuOption[0].Title = DefaultTitle; MenuOption[0].MaxMemory = 0; MenuOption[0].LoadOptions = NULL; MenuOption[0].Win95 = 0; NumberSystems = 1; DefaultSelection = 0; } #if DBG DebugLines = BlpFindSection("[debug]", FileLines, FileLineCount, &DebugLineCount); #endif } // // Parse the [operating systems] section // for (i=0; i MAX_TITLE_LENGTH) { // // This title is too long to fit on one line, so we have to // truncate it. // if (MenuOption[i].EnableDebug == TRUE) { MenuOption[i].Title[MAX_TITLE_LENGTH - strlen(EnabledKd)] = '\0'; } else { MenuOption[i].Title[MAX_TITLE_LENGTH] = '\0'; } CurrentLength = MAX_TITLE_LENGTH; } if (CurrentLength > MaxLength) { MaxLength = CurrentLength; } } Selection = Default; StartTime = GET_COUNTER(); EndTime = StartTime + (Timeout * 182) / 10; BlPrint("OS Loader V4.00\n"); TextSetCurrentAttribute(0x07); Moved = TRUE; do { TextSetCursorPosition(0,2); BlPrint(SelectOs); if(Moved) { for (i=0; i= MaxPage) { // // This memory descriptor lies entirely above the boundary, // eliminate it. // RtlMoveMemory(MDArray+Current, MDArray+Current+1, sizeof(MEMORY_DESCRIPTOR)* (NumberDescriptors-Current-1)); --NumberDescriptors; } else if (MDArray[Current].BasePage + MDArray[Current].PageCount > MaxPage) { // // This memory descriptor crosses the boundary, truncate it. // MDArray[Current].PageCount = MaxPage - MDArray[Current].BasePage; ++Current; } else { // // This one's ok, keep it. // ++Current; } } } ARC_STATUS BlpRenameWin95SystemFile( IN ULONG DriveId, IN ULONG Type, IN PCHAR FileName, IN PCHAR Ext, IN PCHAR NewName ) /*++ Routine Description: Renames a file from one name to another. Arguments: DriveId - Open drive identifier Type - WIN95_DOS or DOS_WIN95 FileName - Base file name Ext - Base extension NewName - Non-NULL value causes an override of a generated name Return Value: Arc status of the failed opperation or E_SUCCESS. --*/ { ARC_STATUS Status; ULONG FileId; ULONG FileIdCur; CHAR Fname[16]; CHAR FnameCur[16]; CHAR FnameNew[16]; if (Type == WIN95_DOS) { sprintf( Fname, "%s.dos", FileName ); } else { if (NewName) { strcpy( Fname, NewName ); } else { sprintf( Fname, "%s.w40", FileName ); } } Status = BlOpen( DriveId, Fname, ArcOpenReadOnly, &FileId ); if (Status != ESUCCESS) { return Status; } sprintf( FnameCur, "%s.%s", FileName, Ext ); Status = BlOpen( DriveId, FnameCur, ArcOpenReadOnly, &FileIdCur ); if (Status != ESUCCESS) { BlClose( FileId ); return Status; } if (Type == WIN95_DOS) { if (NewName) { strcpy( FnameNew, NewName ); } else { sprintf( FnameNew, "%s.w40", FileName ); } } else { sprintf( FnameNew, "%s.dos", FileName ); } Status = BlRename( FileIdCur, FnameNew ); BlClose( FileIdCur ); if (Status != ESUCCESS) { BlClose( FileId ); return Status; } Status = BlRename( FileId, FnameCur ); BlClose( FileId ); return Status; } VOID BlpRenameWin95Files( IN ULONG DriveId, IN ULONG Type ) /*++ Routine Description: Renames all Windows 95 system files from either their Win95 DOS names to their Win95 name or the reverse. Arguments: DriveId - Open drive identifier Type - 1=dos to win95, 2=win95 to dos Return Value: None. --*/ { BlpRenameWin95SystemFile( DriveId, Type, "command", "com", NULL ); BlpRenameWin95SystemFile( DriveId, Type, "msdos", "sys", NULL ); BlpRenameWin95SystemFile( DriveId, Type, "io", "sys", "winboot.sys" ); BlpRenameWin95SystemFile( DriveId, Type, "autoexec", "bat", NULL ); BlpRenameWin95SystemFile( DriveId, Type, "config", "sys", NULL ); }