/*++ Copyright (c) 1991 Microsoft Corporation Module Name: partit.c Abstract: This module contains entry points to perform the 'configure system partition' and 'create OS loader' options of the ARC installer. Author: Ted Miller (tedm) Nov-1991 Revision History: --*/ #include "precomp.h" #pragma hdrstop PCHAR AlGetNextArcNamToken ( IN PCHAR TokenString, OUT PCHAR OutputToken, OUT PULONG UnitNumber ); #define STATUS_ROW_TOP 13 #define STATUS_ROW_BOTTOM 17 char NOMEMMSG[] = "Insufficient memory"; char NOCNFMSG[] = "Unable to determine disk configuration (ARC status = %u)"; char NOFMTMSG[] = "Format failed (ARC status = %u)"; char DSKFLMSG[] = "Disk is full"; char NOCREMSG[] = "Could not create partition (ARC status = %u)"; char NODELMSG[] = "Could not delete partition (ARC status = %u)"; char ALREAMSG[] = "Partition is already a system partition"; char NOFILMSG[] = "Unable to determine filesystem on partition (ARC status = %u)"; char NOENVMSG[] = "Error (ARC status = %u) determining environment"; char NOEVAMSG[] = "Could not add partition to environment (ARC status = %u)"; char NOEVDMSG[] = "Could not remove partition from environment (ARC status = %u)"; char NOSYSMSG[] = "No system partitions defined"; char NOPARMSG[] = "No partitions on this disk"; char SYSPARTVAR[] = "SYSTEMPARTITION"; char OSLOADERVAR[] = "OSLOADER"; char OSLOADPARTVAR[] = "OSLOADPARTITION"; #define MsgNoMem() AlStatusMsg(STATUS_ROW_TOP,STATUS_ROW_BOTTOM,TRUE,NOMEMMSG); PCHAR SysPartMenu[] = { "Create System Partition", "Delete Partition", "Make Existing Partition into System Partition", "Exit" }; #define SYSPARTMENU_CREATE 0 #define SYSPARTMENU_DELETE 1 #define SYSPARTMENU_ADD 2 #define SYSPARTMENU_EXIT 3 #define MENU_ROW 4 char sprintfBuffer[256]; BOOLEAN Confirm( PCHAR Warning ) { char c; ULONG Count; AlClearStatusArea(STATUS_ROW_TOP,STATUS_ROW_BOTTOM); AlPrint("%s%s (y/n)?",MSGMARGIN,Warning); ArcRead(ARC_CONSOLE_INPUT,&c,1,&Count); while((c != 'y') && (c != 'Y') && (c != 'n') && (c != 'N') && (c != ASCI_ESC)) { ArcRead(ARC_CONSOLE_INPUT,&c,1,&Count); } AlClearStatusArea(STATUS_ROW_TOP,STATUS_ROW_BOTTOM); return((BOOLEAN)((c == 'y') || (c == 'Y'))); } VOID PrintErrorMsg( PCHAR FormatString, ... ) { va_list ArgList; va_start(ArgList,FormatString); AlClearStatusArea(STATUS_ROW_TOP,STATUS_ROW_BOTTOM); vAlStatusMsg(STATUS_ROW_TOP,TRUE,FormatString,ArgList); AlWaitKey(NULL); AlClearStatusArea(STATUS_ROW_TOP,STATUS_ROW_BOTTOM); } VOID PrintMsg( PCHAR FormatString, ... ) { va_list ArgList; va_start(ArgList,FormatString); AlClearStatusArea(STATUS_ROW_TOP,STATUS_ROW_BOTTOM); vAlStatusMsg(STATUS_ROW_TOP,FALSE,FormatString,ArgList); AlWaitKey(NULL); AlClearStatusArea(STATUS_ROW_TOP,STATUS_ROW_BOTTOM); } BOOLEAN IsBootSelectionPartition( PCHAR Variable, ULONG Disk, ULONG Partition, PULONG MatchNumber OPTIONAL ) { char text[256]; PCHAR Var = ArcGetEnvironmentVariable(Variable); if (Var == NULL) { return(FALSE); } sprintf(text,"%spartition(%u)",GetDiskName(Disk),Partition); return(AlFindNextMatchComponent(Var,text,0,MatchNumber)); } LONG ChooseDisk( VOID ) { ULONG DiskCount = GetDiskCount(); PVOID MenuID; LONG Disk; ULONG ChosenDisk; PCHAR DiskName,TempDiskName; ULONG UnitNumber,ScsiNumber,ScsiId,DiskNumber; CHAR Token[32]; if (DiskCount == 1) { return(0); } if (!AlNewMenu(&MenuID)) { MsgNoMem(); return(-1); } for(Disk = DiskCount - 1; Disk >= 0; Disk--) { DiskName = GetDiskName(Disk); if ((strstr(DiskName, "scsi") != NULL) && (strstr(DiskName, "disk") != NULL) ) { ScsiNumber = ScsiId = DiskNumber = 0; TempDiskName = DiskName; while (TempDiskName != NULL) { TempDiskName = AlGetNextArcNamToken(TempDiskName, Token, &UnitNumber); if (strcmp(Token,"scsi") == 0) { ScsiNumber = UnitNumber; } if (strcmp(Token,"disk") == 0) { ScsiId = UnitNumber; } if (strcmp(Token,"rdisk") == 0) { DiskNumber = UnitNumber; } } sprintf(sprintfBuffer, "Scsi bus %d, Identifier %d, Disk %d (%s)", ScsiNumber, ScsiId, DiskNumber, GetDiskName(Disk)); } else { sprintf(sprintfBuffer,"Disk %d (%s)",Disk,GetDiskName(Disk)); } if (!AlAddMenuItem(MenuID,sprintfBuffer,Disk,0)) { MsgNoMem(); return(-1); } } if (!AlDisplayMenu(MenuID,FALSE,0,&ChosenDisk,MENU_ROW,"Select Disk")) { return(-1); } else { return(ChosenDisk); } } BOOLEAN // true if partition was created DoPartitionCreate( OUT PULONG DiskNo, OUT PULONG PartitionNo ) { ULONG Disk,i; PREGION_DESCRIPTOR Regions; ULONG RegionCount,Choice; ULONG ChosenSize; ARC_STATUS status; BOOLEAN xAny,xP,xE,xL,PrimaryExists; PVOID MenuID; ULONG PartitionNumber; char PartitionPath[256]; if ((Disk = ChooseDisk()) == -1) { return(FALSE); } if ((status = DoesAnyPrimaryExist(Disk,&PrimaryExists)) != ESUCCESS) { PrintErrorMsg(NOCNFMSG,status); return(FALSE); } if ((status = IsAnyCreationAllowed(Disk, TRUE, &xAny, &xP, &xE, &xL ) ) != ESUCCESS) { PrintErrorMsg(NOCNFMSG,status); return(FALSE); } // in order for a creation to be allowed there must be // - free space on the disk and a free mbr entry OR // - free space in an existing extended partition. if (!xAny) { PrintErrorMsg(DSKFLMSG); return(FALSE); } if ((status = GetFreeDiskRegions(Disk,&Regions,&RegionCount)) != ESUCCESS) { PrintErrorMsg(NOCNFMSG,status); return(FALSE); } if (!AlNewMenu(&MenuID)) { MsgNoMem(); FreeRegionArray(Regions,RegionCount); return(FALSE); } // Present the user with a list of the free spaces // on the disk (and within the extended partition, if it // exists). if (RegionCount > 1) { for(i=0; i Regions[Choice].SizeMB)) { PrintErrorMsg("Invalid size."); } else { break; } } while(1); // The chosen space is either in the extended partition or not. // If it is, just create the requested partition. if (Regions[Choice].RegionType == REGION_LOGICAL) { status = CreatePartition(&Regions[Choice],ChosenSize,REGION_LOGICAL); PartitionNumber = Regions[Choice].PartitionNumber; } else { // The chosen space is not in an extended partition. // If there's already a primary and we can create // an extended partition, then first create an // extended partition spanning the entire space chosen // by the user, and then a logical volume within it of // size entered by the user. Otherwise [ie, there's no primary // or we're not allowed to create an extended partition] // create a primary of the size entered by the user. if (PrimaryExists && xE) { // create extended partition first. status = CreatePartition(&Regions[Choice],Regions[Choice].SizeMB,REGION_EXTENDED); FreeRegionArray(Regions,RegionCount); if ((status = GetFreeLogicalDiskRegions(Disk,&Regions,&RegionCount)) != ESUCCESS) { PrintErrorMsg(NOCNFMSG,status); return(FALSE); } // since we just created the extended partition, there will be one free // region in it. status = CreatePartition(Regions,ChosenSize,REGION_LOGICAL); PartitionNumber = Regions[0].PartitionNumber; } else { status = CreatePartition(&Regions[Choice],ChosenSize,REGION_PRIMARY); PartitionNumber = Regions[Choice].PartitionNumber; } } FreeRegionArray(Regions,RegionCount); if ( (status == ESUCCESS) && ((status = CommitPartitionChanges(Disk)) == ESUCCESS)) { PrintMsg("Partition successfully created."); #if 0 // This is bogus since this routine is called in the code path where // the user is creating a system partition. if (ArcGetEnvironmentVariable(SYSPARTVAR) == NULL) { if (Confirm("Do you want to make this the system partition")) { sprintf(PartitionPath,"%spartition(%u)",GetDiskName(Disk),PartitionNumber); if ((status = ArcSetEnvironmentVariable(SYSPARTVAR,PartitionPath)) != ESUCCESS) { PrintErrorMsg(NOEVAMSG,status); } } } #endif *DiskNo = Disk; *PartitionNo = PartitionNumber; return(TRUE); } else { PrintErrorMsg(NOCREMSG,status); return(FALSE); } } VOID DoPartitionDelete( VOID ) { BOOLEAN xAny,xPrimary,xExtended,xLogical; ARC_STATUS status; PVOID MenuID; ULONG i,RegionCount,Choice; ULONG MatchNumber,Index; LONG Disk; PREGION_DESCRIPTOR Regions; BOOLEAN err,Confirmation; if ((Disk = ChooseDisk()) == -1) { return; } if ((status = DoesAnyPartitionExist(Disk,&xAny,&xPrimary,&xExtended,&xLogical)) != ESUCCESS) { PrintErrorMsg(NOCNFMSG,status); return; } if (xAny) { if (!AlNewMenu(&MenuID)) { MsgNoMem(); return; } if ((status = GetUsedDiskRegions(Disk,&Regions,&RegionCount)) != ESUCCESS) { PrintErrorMsg(NOCNFMSG,status); } else { err = FALSE; for(i=0; i