/*! @file i386/libsaio/bootmap.c @abstract Routines related to the boot volume map. @copyright David Elliott */ #include "libsaio.h" #include "bootmap.h" BootBVMapRef scanBootVolumesOnAllDevices(int firstDev, int *bvCount, bool doCompleteScan) { int biosdev; BootBVMapRef deviceInfoHead = NULL; bool processingFirst = (firstDev >= 0); // If the caller asked for a full count, intiialize it to 0. if(bvCount != NULL) *bvCount = 0; // Start with the firstDev or if not that then 0x80 for( biosdev = processingFirst?firstDev:0x80; // If we had a specific device to process, then process it even if it is non-BIOS processingFirst || biosdev <= 0xff; // If we're not processing the first device, or if the first device is 0x80 then // move on to the next one. Otherwise start the real loop at 0x80 (!processingFirst || biosdev == 0x80)?++biosdev:(biosdev = 0x80) ) { struct driveInfo di; // If we're not processing the first device and we encounter the first device // in the ordinary iteration then don't reprocess it. if(!processingFirst && biosdev == firstDev) continue; // If we have already processed the first device (indicated by the fact that // biosdev != firstDev) then we must clear the processingFirst flag so the // loop iterator will know to do the normal increment. if(processingFirst && biosdev != firstDev) processingFirst = false; // If processing the first device or if we get valid drive info then add // the device to the map and scan it for boot volumes. if( processingFirst || ((getDriveInfo(biosdev, &di) == 0) && (di.valid != 0))) { // Hook the new record at the head of the list. BootBVMapRef currDeviceInfo; currDeviceInfo = malloc(sizeof(*currDeviceInfo)); currDeviceInfo->next = deviceInfoHead; deviceInfoHead = currDeviceInfo; // Fill in the device, bvChain, and bvCount information. currDeviceInfo->biosdev = biosdev; currDeviceInfo->bvChain = scanBootVolumes(biosdev, &(currDeviceInfo->bvCount)); // If the caller asked for the full count, add this device's BV count to it. if(bvCount != NULL) *bvCount += currDeviceInfo->bvCount; } // If reading the drive info failed and caller didn't request a complete scan then // we can stop now. This works under the assumption that at least for hard drive // devices they are always in order like 0x80, 0x81, 0x82, 0x83. Once you find the // first device for which getDriveInfo fails, there's no point in continuing to call // it on later devices and in fact it can be detrimental to our health because some // BIOS will just outright bomb for higher numbered devices. // // So what we _hope_ is that it won't bomb on a 0x8X device but will correctly fail // to get disk info which should stop us here and we won't then probe something that // will actually completely bomb the machine. else if(!doCompleteScan) { break; } } return deviceInfoHead; } void freeBootBVMap(BootBVMapRef head) { while(head) { BootBVMapRef next = head->next; free(head); head = next; } }