Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

low.c

Go to the documentation of this file.
00001 #include "precomp.h" 00002 #pragma hdrstop 00003 #include <bootmbr.h> 00004 00005 ARC_STATUS 00006 LowOpenDisk( 00007 IN PCHAR DevicePath, 00008 OUT PULONG DiskId 00009 ) 00010 /*++ 00011 00012 Routine Description: 00013 00014 This routine opens the supplied device for DASD access. 00015 00016 Arguments: 00017 00018 DevicePath - Supplies the device path to be opened. 00019 DiskId - Returns the disk id. 00020 00021 Return Value: 00022 00023 ArcOpen 00024 00025 --*/ 00026 { 00027 char buffer[256]; 00028 00029 sprintf(buffer,"%spartition(0)",DevicePath); 00030 00031 return ArcOpen(buffer, ArcOpenReadWrite, DiskId); 00032 } 00033 00034 00035 ARC_STATUS 00036 LowCloseDisk( 00037 IN ULONG DiskId 00038 ) 00039 /*++ 00040 00041 Routine Description: 00042 00043 This routine closes the supplied device. 00044 00045 Arguments: 00046 00047 DiskId - Supplies the disk id. 00048 00049 Return Value: 00050 00051 ArcClose 00052 00053 --*/ 00054 { 00055 return ArcClose(DiskId); 00056 } 00057 00058 ARC_STATUS 00059 LowGetDriveGeometry( 00060 IN PCHAR DevicePath, 00061 OUT PULONG TotalSectorCount, 00062 OUT PULONG SectorSize, 00063 OUT PULONG SectorsPerTrack, 00064 OUT PULONG Heads 00065 ) 00066 { 00067 char Buffer[256]; 00068 00069 sprintf(Buffer,"%spartition(0)",DevicePath); 00070 return(LowGetPartitionGeometry(Buffer,TotalSectorCount,SectorSize,SectorsPerTrack,Heads)); 00071 } 00072 00073 00074 00075 ARC_STATUS 00076 LowGetPartitionGeometry( 00077 IN PCHAR PartitionPath, 00078 OUT PULONG TotalSectorCount, 00079 OUT PULONG SectorSize, 00080 OUT PULONG SectorsPerTrack, 00081 OUT PULONG Heads 00082 ) 00083 /*++ 00084 00085 Routine Description: 00086 00087 This routine computes the drive geometry for the given partition or 00088 physical disk. 00089 00090 Arguments: 00091 00092 PartitionPath - Supplies a path to the partition or physical disk. 00093 NumberOfSectors - Returns the number of sectors. 00094 SectorSize - Returns the sector size. 00095 SectorsPerTrack - Returns the number of sectors per track. 00096 Heads - Returns the number of heads. 00097 00098 Return Value: 00099 00100 ArcOpen, ArcGetFileInformation, ArcClose, E2BIG, ESUCCESS 00101 00102 --*/ 00103 { 00104 FILE_INFORMATION file_info; 00105 ARC_STATUS r; 00106 ULONG fileid; 00107 LARGE_INTEGER l; 00108 CM_DISK_GEOMETRY_DEVICE_DATA *DiskGeometry; 00109 CONFIGURATION_COMPONENT *DiskComponent; 00110 CM_PARTIAL_RESOURCE_LIST *DiskConfiguration; 00111 CHAR DataBuffer[sizeof(CM_PARTIAL_RESOURCE_LIST) + 00112 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA)]; 00113 CM_PARTIAL_RESOURCE_DESCRIPTOR *DiskData; 00114 00115 // Always assume 512 bytes per sector. 00116 00117 *SectorSize = 512; 00118 00119 // Assume the SCSI default values for number of heads and sectors per track 00120 00121 *SectorsPerTrack = 32; 00122 *Heads = 64; 00123 00124 // See if there is device specific data describing the geometry of 00125 // the drive. If there is none, then just use the default SCSI 00126 // values. 00127 00128 DiskComponent = ArcGetComponent(PartitionPath); 00129 00130 if (DiskComponent == NULL) { 00131 return EINVAL; 00132 } 00133 00134 // 00135 // See if the ConfigurationDataLength is correct 00136 // It should contain one DeviceSpecific resource descriptor 00137 // 00138 00139 if (DiskComponent->ConfigurationDataLength == sizeof(CM_PARTIAL_RESOURCE_LIST) + 00140 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA) ) { 00141 00142 DiskConfiguration = (CM_PARTIAL_RESOURCE_LIST *)DataBuffer; 00143 00144 r = ArcGetConfigurationData(DiskConfiguration,DiskComponent); 00145 00146 if (r == ESUCCESS) { 00147 00148 // 00149 // See if the Configuration Data has ARC version 1.3 or greater 00150 // 00151 00152 if ( (DiskConfiguration->Version == 1 && DiskConfiguration->Revision >=3 ) || 00153 (DiskConfiguration->Version > 1) ) { 00154 00155 DiskData = &(DiskConfiguration->PartialDescriptors[DiskConfiguration->Count-1]); 00156 00157 if (DiskData->Type == CmResourceTypeDeviceSpecific) { 00158 00159 if (DiskData->u.DeviceSpecificData.DataSize == sizeof(CM_DISK_GEOMETRY_DEVICE_DATA)) { 00160 DiskGeometry = (CM_DISK_GEOMETRY_DEVICE_DATA *) 00161 &(DiskConfiguration->PartialDescriptors[DiskConfiguration->Count]); 00162 *SectorsPerTrack = DiskGeometry->SectorsPerTrack; 00163 *Heads = DiskGeometry->NumberOfHeads; 00164 *SectorSize = DiskGeometry->BytesPerSector; 00165 } 00166 } 00167 } 00168 } 00169 } 00170 00171 // PrintError("SectorSize = %08x",*SectorSize); 00172 // PrintError("SectorsPerTrack = %08x",*SectorsPerTrack); 00173 // PrintError("Heads = %08x",*Heads); 00174 00175 r = ArcOpen(PartitionPath, ArcOpenReadOnly, &fileid); 00176 00177 if (r != ESUCCESS) { 00178 return r; 00179 } 00180 00181 r = ArcGetFileInformation(fileid, &file_info); 00182 00183 if (r != ESUCCESS) { 00184 return r; 00185 } 00186 00187 r = ArcClose(fileid); 00188 00189 if (r != ESUCCESS) { 00190 return r; 00191 } 00192 00193 l.QuadPart = file_info.EndingAddress.QuadPart - 00194 file_info.StartingAddress.QuadPart; 00195 00196 l.QuadPart = ((ULONGLONG)l.QuadPart) / ((ULONGLONG)(*SectorSize)); 00197 00198 if (l.HighPart) { 00199 return E2BIG; 00200 } 00201 00202 *TotalSectorCount = l.LowPart; 00203 00204 return ESUCCESS; 00205 } 00206 00207 00208 #define MAX_TRANSFER 65536 00209 00210 00211 ARC_STATUS 00212 LowReadSectors( 00213 IN ULONG VolumeId, 00214 IN ULONG SectorSize, 00215 IN ULONG StartingSector, 00216 IN ULONG NumberOfSectors, 00217 OUT PVOID Buffer 00218 ) 00219 /*++ 00220 00221 Routine Description: 00222 00223 This routine reads 'NumberOfSectors' sectors starting at sector 00224 'StartingSector' on the volume with ID 'VolumeId'. 00225 00226 Arguments: 00227 00228 VolumeId - Supplies the ID for the volume. 00229 SectorSize - Supplies the number of bytes per sector. 00230 StartingSector - Supplies the starting sector for the read. 00231 NumberOfSectors - Supplies the number of sectors to read. 00232 Buffer - Returns the read in sectors. 00233 00234 Return Value: 00235 00236 ArcSeek, ArcRead, EIO, ESUCCESS 00237 00238 --*/ 00239 { 00240 ARC_STATUS r; 00241 ULONG c; 00242 LARGE_INTEGER l; 00243 ULONG i; 00244 ULONG transfer; 00245 PCHAR buf; 00246 ULONG total; 00247 00248 00249 l.QuadPart = UInt32x32To64(StartingSector,SectorSize); 00250 00251 buf = (PCHAR) Buffer; 00252 00253 r = ArcSeek(VolumeId, &l, SeekAbsolute); 00254 00255 if (r != ESUCCESS) { 00256 return r; 00257 } 00258 00259 total = SectorSize*NumberOfSectors; 00260 00261 for (i = 0; i < total; i += MAX_TRANSFER) { 00262 00263 transfer = min(MAX_TRANSFER, total - i); 00264 00265 r = ArcRead(VolumeId, &buf[i], transfer, &c); 00266 00267 if (r != ESUCCESS) { 00268 return r; 00269 } 00270 00271 if (c != transfer) { 00272 return EIO; 00273 } 00274 } 00275 00276 return ESUCCESS; 00277 } 00278 00279 00280 ARC_STATUS 00281 LowWriteSectors( 00282 IN ULONG VolumeId, 00283 IN ULONG SectorSize, 00284 IN ULONG StartingSector, 00285 IN ULONG NumberOfSectors, 00286 IN PVOID Buffer 00287 ) 00288 /*++ 00289 00290 Routine Description: 00291 00292 This routine write 'NumberOfSectors' sectors starting at sector 00293 'StartingSector' on the volume with ID 'VolumeId'. 00294 00295 Arguments: 00296 00297 VolumeId - Supplies the ID for the volume. 00298 SectorSize - Supplies the number of bytes per sector. 00299 StartingSector - Supplies the starting sector for the write. 00300 NumberOfSectors - Supplies the number of sectors to write. 00301 Buffer - Supplies the sectors to write. 00302 00303 Return Value: 00304 00305 ArcSeek, ArcWrite, EIO, ESUCCESS 00306 00307 --*/ 00308 { 00309 ARC_STATUS r; 00310 ULONG c; 00311 LARGE_INTEGER l; 00312 ULONG i; 00313 ULONG transfer; 00314 PCHAR buf; 00315 ULONG total; 00316 00317 l.QuadPart = UInt32x32To64(StartingSector,SectorSize); 00318 00319 buf = (PCHAR) Buffer; 00320 00321 r = ArcSeek(VolumeId, &l, SeekAbsolute); 00322 00323 if (r != ESUCCESS) { 00324 return r; 00325 } 00326 00327 total = SectorSize*NumberOfSectors; 00328 00329 for (i = 0; i < total; i += MAX_TRANSFER) { 00330 00331 transfer = min(MAX_TRANSFER, total - i); 00332 00333 r = ArcWrite(VolumeId, &buf[i], transfer, &c); 00334 00335 if (r != ESUCCESS) { 00336 return r; 00337 } 00338 00339 if (c != transfer) { 00340 return EIO; 00341 } 00342 } 00343 00344 return ESUCCESS; 00345 } 00346 00347 00348 /******************** DAVIDRO CODE *************************************/ 00349 /*++ 00350 00351 Copyright (c) 1991 Microsoft Corporation 00352 00353 Module Name: 00354 00355 alpath.c 00356 00357 Abstract: 00358 00359 This module provides ARC pathname functions. 00360 00361 Author: 00362 00363 David M. Robinson (davidro) 13-November-1991 00364 00365 Revision History: 00366 00367 --*/ 00368 00369 // 00370 // Define the ARC pathname mnemonics. 00371 // 00372 00373 PCHAR MnemonicTable[] = { 00374 "arc", 00375 "cpu", 00376 "fpu", 00377 "pic", 00378 "pdc", 00379 "sic", 00380 "sdc", 00381 "sc", 00382 "eisa", 00383 "tc", 00384 "scsi", 00385 "dti", 00386 "multi", 00387 "disk", 00388 "tape", 00389 "cdrom", 00390 "worm", 00391 "serial", 00392 "net", 00393 "video", 00394 "par", 00395 "point", 00396 "key", 00397 "audio", 00398 "other", 00399 "rdisk", 00400 "fdisk", 00401 "tape", 00402 "modem", 00403 "monitor", 00404 "print", 00405 "pointer", 00406 "keyboard", 00407 "term", 00408 "other", 00409 "line", 00410 "netper", 00411 "memory" 00412 }; 00413 00414 // 00415 // Static storage for the pathname return value. 00416 // 00417 00418 CHAR Pathname[256]; 00419 00420 00421 PCHAR 00422 AlGetPathnameFromComponent ( 00423 IN PCONFIGURATION_COMPONENT Component 00424 ) 00425 00426 /*++ 00427 00428 Routine Description: 00429 00430 This function builds an ARC pathname for the specified component. 00431 00432 Arguments: 00433 00434 Component - Supplies a pointer to a configuration component. 00435 00436 Return Value: 00437 00438 Returns a pointer to a string which contains the ARC pathname for the 00439 component. NOTE: The string is stored in static storage, and must be 00440 copied by the user before another call to this routine. 00441 00442 --*/ 00443 { 00444 PCONFIGURATION_COMPONENT ParentComponent; 00445 CHAR NewSegment[16]; 00446 CHAR Tempname[256]; 00447 00448 Pathname[0] = 0; 00449 00450 // 00451 // Loop while not at the root component. 00452 // 00453 00454 while ((ParentComponent = ArcGetParent(Component)) != NULL) { 00455 00456 // 00457 // Build new pathname segment from the Component type and key. 00458 // 00459 00460 sprintf(NewSegment, 00461 "%s(%d)", 00462 MnemonicTable[Component->Type], 00463 Component->Key); 00464 00465 // 00466 // Add the new segment as a prefix of the current pathname. 00467 // 00468 00469 strcpy(Tempname, Pathname); 00470 strcpy(Pathname, NewSegment); 00471 strcat(Pathname, Tempname); 00472 00473 // 00474 // Move to the parent component. 00475 // 00476 00477 Component = ParentComponent; 00478 } 00479 00480 return Pathname; 00481 } 00482 /******************* END OF DAVIDRO CODE *********************************/ 00483 00484 00485 ARC_STATUS 00486 LowQueryPathFromComponent( 00487 IN PCONFIGURATION_COMPONENT Component, 00488 OUT PCHAR* Path 00489 ) 00490 /*++ 00491 00492 Routine Description: 00493 00494 This routine computes a path from a component. The resulting 00495 path is allocated on the heap. 00496 00497 Arguments: 00498 00499 Component - Supplies a component. 00500 Path - Returns the path corresponding to that component. 00501 00502 Return Value: 00503 00504 ENOMEM, ESUCCESS 00505 00506 --*/ 00507 { 00508 PCHAR p; 00509 PCHAR path; 00510 00511 p = AlGetPathnameFromComponent(Component); 00512 00513 path = AllocateMemory(strlen(p) + 1); 00514 00515 if (!path) { 00516 return ENOMEM; 00517 } 00518 00519 strcpy(path, p); 00520 00521 *Path = path; 00522 00523 return ESUCCESS; 00524 } 00525 00526 00527 ARC_STATUS 00528 LowTraverseChildren( 00529 IN PCONFIGURATION_COMPONENT Parent, 00530 IN CONFIGURATION_CLASS* ConfigClass OPTIONAL, 00531 IN CONFIGURATION_TYPE* ConfigType OPTIONAL, 00532 IN OUT PCONFIGURATION_COMPONENT* MatchingArray OPTIONAL, 00533 IN OUT PULONG CurrentLength 00534 ) 00535 /*++ 00536 00537 Routine Description: 00538 00539 This routine traverses the trees whose parent is 'Parent'. 00540 If the Matching array is provided then it will be filled 00541 with pointers to all of the components whose type and class 00542 match 'ConfigType' and 'ConfigClass'. Also, the 'CurrentLength' 00543 is incremented by the number of nodes that match. 00544 00545 Arguments: 00546 00547 Parent - Supplies the root of the tree. 00548 ConfigClass - Supplies the class to search for. 00549 ConfigType - Supplies the type to search for. 00550 CurrentLength - Supplies the current count. 00551 00552 Return Value: 00553 00554 ESUCCESS 00555 00556 --*/ 00557 { 00558 PCONFIGURATION_COMPONENT pc; 00559 ARC_STATUS r; 00560 00561 if (!(pc = ArcGetChild(Parent))) { 00562 return ESUCCESS; 00563 } 00564 00565 for (;;) { 00566 00567 if ((!ConfigClass || pc->Class == *ConfigClass) && 00568 (!ConfigType || pc->Type == *ConfigType)) { 00569 00570 if (MatchingArray) { 00571 00572 MatchingArray[*CurrentLength] = pc; 00573 } 00574 00575 (*CurrentLength)++; 00576 } 00577 00578 r = LowTraverseChildren(pc, ConfigClass, ConfigType, 00579 MatchingArray, CurrentLength); 00580 00581 if (r != ESUCCESS) { 00582 return r; 00583 } 00584 00585 if (!(pc = ArcGetPeer(pc))) { 00586 break; 00587 } 00588 } 00589 00590 return ESUCCESS; 00591 } 00592 00593 00594 ARC_STATUS 00595 LowQueryComponentList( 00596 IN CONFIGURATION_CLASS* ConfigClass OPTIONAL, 00597 IN CONFIGURATION_TYPE* ConfigType OPTIONAL, 00598 OUT PCONFIGURATION_COMPONENT** ComponentList, 00599 OUT PULONG ListLength 00600 ) 00601 /*++ 00602 00603 Routine Description: 00604 00605 This routine returns an array of components whose class and 00606 type match the ones given. (Since each parameter is optional, 00607 you can do type-only and class-only searches.) 00608 00609 The array is allocated on the heap and contains pointers to 00610 the actual components (NOT copies). 00611 00612 Arguments: 00613 00614 ConfigClass - Supplies the configuation class to search for. 00615 ConfigType - Supplies the configuration type to search for. 00616 ComponentList - Returns a list of pointers to components whose 00617 class and type match 'ConfigClass' and 00618 'ConfigType'. 00619 ListLength - Returns the number of components in the list. 00620 00621 Return Value: 00622 00623 LowTraverseChildren, ENOMEM 00624 00625 --*/ 00626 { 00627 ARC_STATUS r; 00628 00629 *ListLength = 0; 00630 00631 r = LowTraverseChildren(NULL, ConfigClass, ConfigType, NULL, ListLength); 00632 00633 if (r != ESUCCESS) { 00634 return r; 00635 } 00636 00637 if (!(*ComponentList = (PCONFIGURATION_COMPONENT*) AllocateMemory( 00638 (*ListLength)*sizeof(PCONFIGURATION_COMPONENT)))) { 00639 00640 return ENOMEM; 00641 } 00642 00643 *ListLength = 0; 00644 00645 return LowTraverseChildren(NULL, ConfigClass, ConfigType, 00646 *ComponentList, ListLength); 00647 } 00648 00649 00650 ARC_STATUS 00651 LowQueryPathList( 00652 IN CONFIGURATION_CLASS* ConfigClass OPTIONAL, 00653 IN CONFIGURATION_TYPE* ConfigType OPTIONAL, 00654 OUT PCHAR** PathList, 00655 OUT PULONG ListLength 00656 ) 00657 /*++ 00658 00659 Routine Description: 00660 00661 This routine returns a list of paths to the components that are 00662 of class ConfigClass and of type ConfigType. 00663 00664 Arguments: 00665 00666 ConfigClass - Supplies the configuation class to search for. 00667 ConfigType - Supplies the configuration type to search for. 00668 PathList - Returns a list of paths to the components. 00669 ListLength - Returns the number of components in the list. 00670 00671 Return Value: 00672 00673 LowQueryComponentList, LowQueryPathFromComponent 00674 00675 --*/ 00676 { 00677 PCONFIGURATION_COMPONENT* component_list; 00678 ULONG list_length; 00679 ARC_STATUS r; 00680 ULONG i; 00681 PCHAR* path_list; 00682 00683 r = LowQueryComponentList(ConfigClass, ConfigType, 00684 &component_list, &list_length); 00685 00686 if (r != ESUCCESS) { 00687 return r; 00688 } 00689 00690 if (!(path_list = (PCHAR*) AllocateMemory(list_length*sizeof(PCHAR)))) { 00691 FreeMemory(component_list); 00692 return ENOMEM; 00693 } 00694 00695 00696 for (i = 0; i < list_length; i++) { 00697 path_list[i] = NULL; 00698 } 00699 00700 for (i = 0; i < list_length; i++) { 00701 00702 r = LowQueryPathFromComponent(component_list[i], &path_list[i]); 00703 00704 if (r != ESUCCESS) { 00705 FreeMemory(component_list); 00706 LowFreePathList(path_list, list_length); 00707 return r; 00708 } 00709 } 00710 00711 FreeMemory(component_list); 00712 00713 *PathList = path_list; 00714 *ListLength = list_length; 00715 00716 return ESUCCESS; 00717 } 00718 00719 00720 ARC_STATUS 00721 LowFreePathList( 00722 IN PCHAR* PathList, 00723 IN ULONG ListLength 00724 ) 00725 /*++ 00726 00727 Routine Description: 00728 00729 This routine frees up the space taken by the path lists. 00730 00731 Arguments: 00732 00733 PathList - Supplies the paths. 00734 ListLength - Supplies the number of paths. 00735 00736 Return Value: 00737 00738 ESUCCESS 00739 00740 --*/ 00741 { 00742 ULONG i; 00743 00744 for (i = 0; i < ListLength; i++) { 00745 if (PathList[i]) { 00746 FreeMemory(PathList[i]); 00747 } 00748 } 00749 FreeMemory(PathList); 00750 00751 return ESUCCESS; 00752 } 00753 00754 00755 ARC_STATUS 00756 LowQueryFdiskPathList( 00757 OUT PCHAR** PathList, 00758 OUT PULONG ListLength 00759 ) 00760 /*++ 00761 00762 Routine Description: 00763 00764 This routine returns a list of paths to all the devices of interest 00765 to FDISK. 00766 00767 Arguments: 00768 00769 PathList - Returns a list of paths. 00770 ListLength - Returns the length of the list. 00771 00772 Return Value: 00773 00774 LowQueryComponentList, LowQueryPathFromComponent, ESUCCESS 00775 00776 --*/ 00777 { 00778 CONFIGURATION_TYPE config_type; 00779 00780 config_type = DiskPeripheral; 00781 return LowQueryPathList(NULL, &config_type, PathList, ListLength); 00782 } 00783 00784 00785 ARC_STATUS 00786 LowFreeFdiskPathList( 00787 IN OUT PCHAR* PathList, 00788 IN ULONG ListLength 00789 ) 00790 /*++ 00791 00792 Routine Description: 00793 00794 This routine frees up the space taken by the path lists. 00795 00796 Arguments: 00797 00798 PathList - Supplies the paths. 00799 ListLength - Supplies the number of paths. 00800 00801 Return Value: 00802 00803 ESUCCESS 00804 00805 --*/ 00806 { 00807 return LowFreePathList(PathList, ListLength); 00808 } 00809 00810 00811 ARC_STATUS 00812 LowGetDiskLayout( 00813 IN PCHAR Path, 00814 OUT PDRIVE_LAYOUT_INFORMATION* DriveLayout 00815 ) 00816 { 00817 ARC_STATUS status; 00818 ULONG Handle; 00819 ULONG i,ExtendedStart,BootSector,Entry; 00820 ULONG dummy,bps; 00821 BOOLEAN Link,mbr; 00822 PDRIVE_LAYOUT_INFORMATION DriveInfo; 00823 PPARTITION_INFORMATION p; 00824 PCHAR SectorBuffer; 00825 PPARTITION_DESCRIPTOR ptable; 00826 00827 00828 #define PSTART(p) ( \ 00829 (ULONG) ((p)->StartingSectorLsb0) + \ 00830 (ULONG) ((p)->StartingSectorLsb1 << 8) + \ 00831 (ULONG) ((p)->StartingSectorMsb0 << 16) + \ 00832 (ULONG) ((p)->StartingSectorMsb1 << 24) ) 00833 00834 #define PLENGTH(p) ( \ 00835 (ULONG) ((p)->PartitionLengthLsb0) + \ 00836 (ULONG) ((p)->PartitionLengthLsb1 << 8) + \ 00837 (ULONG) ((p)->PartitionLengthMsb0 << 16) + \ 00838 (ULONG) ((p)->PartitionLengthMsb1 << 24) ) 00839 00840 00841 00842 if((DriveInfo = AlAllocateHeap(sizeof(DRIVE_LAYOUT_INFORMATION) + (500*sizeof(PARTITION_INFORMATION)))) == NULL) { 00843 return(ENOMEM); 00844 } 00845 p = &DriveInfo->PartitionEntry[0]; 00846 00847 if((status = LowGetDriveGeometry(Path,&dummy,&bps,&dummy,&dummy)) != ESUCCESS) { 00848 AlDeallocateHeap(DriveInfo); 00849 return(status); 00850 } 00851 00852 if((SectorBuffer = AlAllocateHeap(bps)) == NULL) { 00853 AlDeallocateHeap(DriveInfo); 00854 return(ENOMEM); 00855 } 00856 00857 ptable = (PPARTITION_DESCRIPTOR)(SectorBuffer + (2*PARTITION_TABLE_OFFSET)); 00858 00859 if((status = LowOpenDisk(Path,&Handle)) != ESUCCESS) { 00860 AlDeallocateHeap(SectorBuffer); 00861 AlDeallocateHeap(DriveInfo); 00862 return(status); 00863 } 00864 00865 mbr = TRUE; 00866 Entry = 0; 00867 BootSector = 0; 00868 ExtendedStart = 0; 00869 status = ESUCCESS; 00870 00871 do { 00872 00873 if((status = LowReadSectors(Handle,bps,BootSector,1,SectorBuffer)) != ESUCCESS) { 00874 break; 00875 } 00876 00877 // This is to catch the case where there is no MBR yet. 00878 00879 if(((PUSHORT)SectorBuffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) { 00880 break; 00881 } 00882 00883 Link = FALSE; 00884 00885 for(i=0; i<NUM_PARTITION_TABLE_ENTRIES; i++) { 00886 00887 if(ptable[i].PartitionType == SYSID_UNUSED) { 00888 00889 // set as unused. 00890 00891 p[Entry].PartitionType = SYSID_UNUSED; 00892 p[Entry].BootIndicator = FALSE; 00893 p[Entry].RewritePartition = FALSE; 00894 p[Entry].PartitionLength.QuadPart = 0; 00895 p[Entry].HiddenSectors = 0; 00896 p[Entry].StartingOffset.QuadPart = 0; 00897 p[Entry].RecognizedPartition = FALSE; 00898 00899 } else { 00900 00901 LARGE_INTEGER Result1, Result2; 00902 00903 p[Entry].PartitionType = ptable[i].PartitionType; 00904 p[Entry].BootIndicator = ptable[i].ActiveFlag; 00905 p[Entry].RewritePartition = FALSE; 00906 p[Entry].PartitionLength.QuadPart = UInt32x32To64(PLENGTH(ptable + i),bps); 00907 00908 // BUGBUG (tedm) the following are not correct for link 00909 // entries in the extended partition. 00910 // But fdisk does not use these values in 00911 // this case so blow it off. As of 00912 // 11/13/91, IoReadPartitionTable has the 00913 // same bug. 00914 00915 p[Entry].HiddenSectors = PSTART(ptable + i); 00916 Result1.QuadPart = UInt32x32To64(PSTART(ptable + i),bps); 00917 Result2.QuadPart = UInt32x32To64(BootSector,bps); 00918 p[Entry].StartingOffset.QuadPart = Result1.QuadPart + Result2.QuadPart; 00919 00920 p[Entry].RecognizedPartition = TRUE; // BUGBUG this is broken 00921 00922 if(p[Entry].PartitionType == SYSID_EXTENDED) { 00923 00924 Link = TRUE; 00925 00926 if(mbr) { 00927 mbr = FALSE; 00928 BootSector = PSTART(ptable + i); 00929 ExtendedStart = BootSector; 00930 } else { 00931 BootSector = ExtendedStart + PSTART(ptable + i); 00932 } 00933 } 00934 } 00935 Entry++; 00936 } 00937 } while(Link); 00938 00939 LowCloseDisk(Handle); 00940 00941 AlDeallocateHeap(SectorBuffer); 00942 00943 if(status != ESUCCESS) { 00944 00945 AlDeallocateHeap(DriveInfo); 00946 return(status); 00947 } 00948 00949 // reallocate DriveInfo, set PartitionCount field. 00950 // DriveInfo is shrinking. 00951 00952 DriveInfo = AlReallocateHeap(DriveInfo, 00953 sizeof(DRIVE_LAYOUT_INFORMATION) 00954 + ((Entry - 1) * sizeof(PARTITION_INFORMATION)) 00955 ); 00956 00957 DriveInfo->PartitionCount = Entry; 00958 00959 *DriveLayout = DriveInfo; 00960 00961 return(ESUCCESS); 00962 } 00963 00964 00965 // 00966 // cylinder/head/sector stuff placed in partition table 00967 // 00968 00969 typedef struct _tagCHS { 00970 USHORT StartCylinder; 00971 UCHAR StartHead; 00972 UCHAR StartSector; 00973 USHORT EndCylinder; 00974 UCHAR EndHead; 00975 UCHAR EndSector; 00976 } CHS, *PCHS; 00977 00978 00979 VOID 00980 CalculateCHSVals( 00981 IN ULONG Start, 00982 IN ULONG Size, 00983 IN ULONG spt, 00984 IN ULONG h, 00985 OUT PCHS chs 00986 ) 00987 { 00988 ULONG spc = spt * h; // sectors per cylinder 00989 ULONG r; 00990 ULONG End = Start+Size-1; 00991 00992 chs->StartCylinder = (USHORT)(Start/spc); 00993 r = Start % spc; 00994 chs->StartHead = (UCHAR)(r / spt); 00995 chs->StartSector = (UCHAR)((r % spt) + 1); // sector is 1-based 00996 00997 chs->EndCylinder = (USHORT)(End/spc); 00998 r = End % spc; 00999 chs->EndHead = (UCHAR)(r / spt); 01000 chs->EndSector = (UCHAR)((r % spt) + 1); // sector is 1-based 01001 } 01002 01003 01004 VOID 01005 SetPartitionTableEntry( 01006 IN OUT PPARTITION_DESCRIPTOR p, 01007 IN UCHAR Active, 01008 IN UCHAR SysID, 01009 IN ULONG RelativeSector, 01010 IN ULONG SectorCount, 01011 IN PCHS chs 01012 ) 01013 { 01014 // first get the easy ones out of the way. 01015 01016 p->ActiveFlag = Active; 01017 p->PartitionType = SysID; 01018 01019 if(chs) { 01020 p->StartingTrack = chs->StartHead; 01021 p->EndingTrack = chs->EndHead; 01022 } else { 01023 p->StartingTrack = 0; 01024 p->EndingTrack = 0; 01025 } 01026 01027 if(chs) { 01028 01029 // pack sector/cyl values 01030 01031 p->StartingCylinderLsb = (chs->StartSector & 0x3f) | ((chs->StartCylinder >> 2) & 0xc0); 01032 p->StartingCylinderMsb = (UCHAR)chs->StartCylinder; 01033 01034 p->EndingCylinderLsb = (chs->EndSector & 0x3f) | ((chs->EndCylinder >> 2) & 0xc0); 01035 p->EndingCylinderMsb = (UCHAR)chs->EndCylinder; 01036 01037 } else { 01038 01039 p->StartingCylinderLsb = 0; 01040 p->StartingCylinderMsb = 0; 01041 01042 p->EndingCylinderLsb = 0; 01043 p->EndingCylinderMsb = 0; 01044 } 01045 01046 // now handle the relative and total sector counts 01047 01048 p->StartingSectorLsb0 = (UCHAR)(RelativeSector >> 0 ); 01049 p->StartingSectorLsb1 = (UCHAR)(RelativeSector >> 8 ); 01050 p->StartingSectorMsb0 = (UCHAR)(RelativeSector >> 16); 01051 p->StartingSectorMsb1 = (UCHAR)(RelativeSector >> 24); 01052 01053 p->PartitionLengthLsb0 = (UCHAR)(SectorCount >> 0 ); 01054 p->PartitionLengthLsb1 = (UCHAR)(SectorCount >> 8 ); 01055 p->PartitionLengthMsb0 = (UCHAR)(SectorCount >> 16); 01056 p->PartitionLengthMsb1 = (UCHAR)(SectorCount >> 24); 01057 } 01058 01059 01060 #define ZeroPartitionTableEntry(p) SetPartitionTableEntry(p,0,SYSID_UNUSED,0,0,NULL); 01061 01062 VOID 01063 ZeroPartitionTable( 01064 PPARTITION_DESCRIPTOR PartitionTable 01065 ) 01066 { 01067 ULONG i; 01068 01069 for(i=0; i<ENTRIES_PER_BOOTSECTOR; i++) { 01070 ZeroPartitionTableEntry(PartitionTable+i); 01071 } 01072 } 01073 01074 01075 ARC_STATUS 01076 LowSetDiskLayout( 01077 IN PCHAR Path, 01078 IN PDRIVE_LAYOUT_INFORMATION DriveLayout 01079 ) 01080 { 01081 ARC_STATUS status; 01082 ULONG dummy,bps,spt,h; 01083 PCHAR SectorBuffer; 01084 ULONG Handle; 01085 PPARTITION_DESCRIPTOR PartitionTable; 01086 PPARTITION_INFORMATION p; 01087 BOOLEAN mbr = TRUE,Update; 01088 ULONG BootSector = 0,ExtendedPartitionStart = 0, 01089 NextBootSector; 01090 ULONG i,j,UsedCount; 01091 CHS chs; 01092 01093 01094 #define SECCNT(l) ((ULONG)(((ULONGLONG)l.QuadPart)/((ULONGLONG)bps))) 01095 01096 01097 ASRT(DriveLayout->PartitionCount); 01098 01099 if((status = LowGetDriveGeometry(Path,&dummy,&bps,&spt,&h)) != ESUCCESS) { 01100 return(status); 01101 } 01102 01103 // allocate a buffer for sector I/O 01104 01105 if((SectorBuffer = AlAllocateHeap(bps)) == NULL) { 01106 return(ENOMEM); 01107 } 01108 01109 // 01110 // Use x86 bootcode as a template so the disk will boot an x86 01111 // if it is moved to disk0 on an x86 machine. 01112 // 01113 RtlMoveMemory(SectorBuffer,x86BootCode,min(X86BOOTCODE_SIZE,bps)); 01114 01115 ((PUSHORT)SectorBuffer)[BOOT_SIGNATURE_OFFSET] = BOOT_RECORD_SIGNATURE; 01116 PartitionTable = (PPARTITION_DESCRIPTOR)(&(((PUSHORT)SectorBuffer)[PARTITION_TABLE_OFFSET])); 01117 01118 if((status = LowOpenDisk(Path,&Handle)) != ESUCCESS) { 01119 AlDeallocateHeap(SectorBuffer); 01120 return(status); 01121 } 01122 01123 ASRT(!(DriveLayout->PartitionCount % ENTRIES_PER_BOOTSECTOR)); 01124 for(i=0; i<DriveLayout->PartitionCount; i+=ENTRIES_PER_BOOTSECTOR) { 01125 01126 Update = FALSE; 01127 UsedCount = 0; 01128 01129 ZeroPartitionTable(PartitionTable); 01130 01131 for(j=0; j<ENTRIES_PER_BOOTSECTOR; j++) { 01132 01133 p = &DriveLayout->PartitionEntry[i+j]; 01134 01135 switch(p->PartitionType) { 01136 case SYSID_UNUSED: 01137 ZeroPartitionTableEntry(PartitionTable+j); 01138 break; 01139 01140 case SYSID_EXTENDED: 01141 NextBootSector = SECCNT(p->StartingOffset); 01142 CalculateCHSVals(NextBootSector,SECCNT(p->PartitionLength),spt,h,&chs); 01143 SetPartitionTableEntry(PartitionTable+j, 01144 p->BootIndicator, 01145 SYSID_EXTENDED, 01146 SECCNT(p->StartingOffset) - ExtendedPartitionStart, 01147 SECCNT(p->PartitionLength), 01148 &chs 01149 ); 01150 if(mbr) { 01151 mbr = FALSE; 01152 ExtendedPartitionStart = NextBootSector; 01153 } 01154 break; 01155 01156 default: 01157 CalculateCHSVals(SECCNT(p->StartingOffset),SECCNT(p->PartitionLength),spt,h,&chs); 01158 SetPartitionTableEntry(PartitionTable+j, 01159 p->BootIndicator, 01160 p->PartitionType, 01161 SECCNT(p->StartingOffset) - BootSector, 01162 SECCNT(p->PartitionLength), 01163 &chs 01164 ); 01165 break; 01166 } 01167 Update = Update || p->RewritePartition; 01168 01169 if(p->PartitionType != SYSID_UNUSED) { 01170 UsedCount++; 01171 } 01172 } 01173 if(Update || !UsedCount) { 01174 if((status = LowWriteSectors(Handle,bps,BootSector,1,SectorBuffer)) != ESUCCESS) { 01175 LowCloseDisk(Handle); 01176 AlDeallocateHeap(SectorBuffer); 01177 return(status); 01178 } 01179 } 01180 BootSector = NextBootSector; 01181 } 01182 01183 LowCloseDisk(Handle); 01184 AlDeallocateHeap(SectorBuffer); 01185 return(ESUCCESS); 01186 }

Generated on Sat May 15 19:40:39 2004 for test by doxygen 1.3.7