Exemplo n.º 1
0
int dsreference_equal(dsreference *r1, dsreference *r2)
{
	/* Compare UUID first, most unique. */
	if (!IsNullUuid(r1->uuid) && !IsNullUuid(r2->uuid))
	{
		if (memcmp(&r1->uuid, &r2->uuid, sizeof(dsuuid_t)) != 0)
			return 0;
	}

	if (r1->dn != NULL && r2->dn != NULL)
	{
		if (!dsdata_equal(r1->dn, r2->dn))
			return 0;
	}

	if (r1->name != NULL && r2->name != NULL)
	{
		if (!dsdata_equal(r1->name, r2->name))
			return 0;
	}

	if (r1->dsid != r2->dsid)
		return 0;

	if (r1->serial != r2->serial)
		return 0;

	if (r1->vers != r2->vers)
		return 0;

	if (r1->timestamp != r2->timestamp)
		return 0;

	return 1;
}
Exemplo n.º 2
0
int GptAllocFileCopy(HGPT hGPT, char *pszFileName, EFI_PARTITION_ENTRY *pNewEntry)
    {
    int i;
    int iPartition;
    QWORD qwLBA;
    int iErr;
    // To be cleaned up before return
    char *pSect = (char *)NULL;
    // End of clean-up zone
    int nSect;
    FILE *hf = NULL;
    
    // Compute the number of partition entries per sector.
    // int iEntryPerSect = hGPT->iSectorSize / sizeof(EFI_PARTITION_ENTRY);

    // Allocate a buffer to access drive data.
    pSect = (char *)malloc(hGPT->iSectorSize);
    if (!pSect) GptAllocFileCopyFail(-4);
    	
    // Open the partition image file
    hf = fopen(pszFileName, "rb");
    if (!hf) GptAllocFileCopyFail(-10);
    // Compute the number of sectors necessary.
    nSect = (int)((_filelength(_fileno(hf)) + hGPT->iSectorSize - 1) / hGPT->iSectorSize);

    // Search the smallest contiguous block of free sectors large enough.
    pNewEntry->EndingLBA = nSect;
    iPartition = GptAllocSectors(hGPT, pNewEntry);  // Side effect: pNewEntry->PartitionTypeGUID = 0;
    if (iPartition < 0) GptAllocFileCopyFail(iPartition);

#ifdef _DEBUG
    if (iVerbose)
        {
        printf("Allocating partition entry #%d for copying from file %s\n", iPartition, pszFileName);
        }
#endif
	    
    // Write the partition contents
    for (i=0, qwLBA=pNewEntry->StartingLBA; i<nSect; i++, qwLBA++)
        {
        size_t stRead;
	        
        stRead = fread(pSect, 1, hGPT->iSectorSize, hf);
        if (stRead < (size_t)(hGPT->iSectorSize)) memset(pSect+stRead, 0, hGPT->iSectorSize-stRead);
	        
	// ~~jfl 2001/12/19 Use the partition type GUID specified in the file, if any.
	if (i==0)
	    {
	    EFI_BOOT_PROGRAM_HEADER *pHdr = (EFI_BOOT_PROGRAM_HEADER *)pSect;
	    if (CheckCrc(hGPT->iSectorSize, &(pHdr->Header)))
		{
		if (!memcmp(((char *)&(pHdr->Header.Signature))+3, "MBR32", 5))
		    {
		    pNewEntry->PartitionTypeGUID = guidMbrBackup;   // If it's inside the GPT, then it's the backup!
		    }
		else	// Assume it's a relay or a boot program (Including the boot menu).
		    {	// Both have a partition entry behind the header.
		    pNewEntry->PartitionTypeGUID = pHdr->Partition.PartitionTypeGUID;
		    }
		}
	    else if (   (!memcmp(((char *)&(pHdr->Header.Signature))+3, "Relay", 5))
		     && (!uuidcmp(&(pHdr->Partition.PartitionTypeGUID), &guidRelay))
		    )	// It's a relay, but with the header incomplete (CRC not set yet).
		{
		pNewEntry->PartitionTypeGUID = guidRelay;
		// ~~jfl 2002/01/03 Update the partition header while we have it.
		uuid_create((uuid_t *)&(pHdr->Partition.UniquePartitionGUID));	// Generate a new GUID
		SetCrc(&(pHdr->Header));
		}
	    else if (IsMBR(pSect))	// Master Boot Record. Assume it's a hard disk.
		{
		pNewEntry->PartitionTypeGUID = guidHardDiskImage;
		}
	    if (IsNullUuid((uuid_t*)&(pNewEntry->PartitionTypeGUID)))	// Assume anything else is a floppy.
		{
		pNewEntry->PartitionTypeGUID = guidFloppyImage;
		}
	    }

	iErr = GptBlockWrite(hGPT, qwLBA, 1, pSect);
	if (iErr) GptAllocFileCopyFail(-3);
        }

copy_return:
    // Cleanup
    fclose(hf);
    free(pSect);
    
    return iPartition;    
    }
Exemplo n.º 3
0
int GptAllocSectors(HGPT hGPT, EFI_PARTITION_ENTRY *pNewEntry)
    {
    int iPartition;
    int iNewPartition = -1;
    QWORD qwFirst = qwZero;
    QWORD qwLast = qwZero;
    // To be cleaned up before return
    QWORD *pqwFirst = (QWORD *)NULL;
    QWORD *pqwLast = (QWORD *)NULL;
    char *pGptEntryBuf = (char *)NULL;
    // End of clean-up zone
    EFI_PARTITION_ENTRY *pPartEntry;
    DWORD dwGptSect;
    int iIndex;
    int iErr;
    int j;
    DWORD dwNewSector;
    int iNewIndex;
    int nBlocks = 1;
#ifdef _DEBUG
    char szBuf1[20];
    char szBuf2[20];
#endif
    QWORD qwForceSect = pNewEntry->StartingLBA;
    QWORD qwNSect = pNewEntry->EndingLBA;
    
#ifdef _DEBUG
    if (iDebug) printf("GptAllocSectors(hBlockDev=%p, nSect=%s, forceSect=%s)\n",
                       hGPT->hBlockDev, qwtox(qwNSect, szBuf1), qwtox(qwForceSect, szBuf2));
#endif

    // Compute the number of partition entries per sector.
    int iEntryPerSect = hGPT->iSectorSize / sizeof(EFI_PARTITION_ENTRY);
        
    // Allocate buffers to access drive data.
    pGptEntryBuf = (char *)malloc(hGPT->iSectorSize);
    if (!pGptEntryBuf) GptAllocSectorsFail(-4);
    pPartEntry = (EFI_PARTITION_ENTRY *)pGptEntryBuf;
    	
    // Search the smallest contiguous block of free sectors large enough.
    // For that, build a list of the free disk areas.
    pqwFirst = (QWORD *)malloc(sizeof(QWORD) * (size_t)hGPT->pGptHdr->NumberOfPartitionEntries);
    pqwLast =  (QWORD *)malloc(sizeof(QWORD) * (size_t)hGPT->pGptHdr->NumberOfPartitionEntries);
    if (!pqwFirst || !pqwLast) GptAllocSectorsFail(-4);

    // Initially, assume all the GPT-managed area is free.
    pqwFirst[0] = hGPT->pGptHdr->FirstUsableLBA;
    pqwLast[0] = hGPT->pGptHdr->LastUsableLBA;

    // Then progress negatively, removing chunks of allocated space.
    for (iPartition = 0, iIndex = 0, dwGptSect=(DWORD)(hGPT->pGptHdr->PartitionEntryLBA);
    	 iPartition < (int)(hGPT->pGptHdr->NumberOfPartitionEntries);
    	 iPartition++, iIndex = (int)(iPartition % iEntryPerSect), dwGptSect += iIndex ? 0 : 1
    	)
    	{
    	if (iIndex == 0) // Read-in a new sector when passing a boundary.
	    {
	    QWORD qw;
	    iErr = GptBlockRead(hGPT, qw = dwGptSect, 1, pGptEntryBuf);
	    if (iErr) GptAllocSectorsFail(-3);
    	    }
    	// Skip unused entries, but keep mark of the first one.
    	if (IsNullUuid((uuid_t*)&(pPartEntry[iIndex].PartitionTypeGUID))) 
    	    {
	    // If we already have found an unused spot, just loop.
	    if (iNewPartition != -1) continue;
		    
	    // OK. Let's use this one for the allocation below.
	    iNewPartition = iPartition;
	    dwNewSector = dwGptSect;
	    iNewIndex = iIndex;
    	    continue;
    	    }
	    	
    	// This entry is in use. Record what sector area it uses.
	// printfx("Removing block %s", pPartEntry[iIndex].StartingLBA);
	// printfx("-%s\n", pPartEntry[iIndex].EndingLBA);
    	for (j=0; j<nBlocks; j++)
    	    {
    	    if (pPartEntry[iIndex].StartingLBA <= pqwLast[j])	// Then insert a hole in this segment
    	        {
    	        int k;
	    	        
    	        if (   (pqwFirst[j] < pPartEntry[iIndex].StartingLBA)
    	            && (pPartEntry[iIndex].EndingLBA < pqwLast[j]) )
    	            {	// If both ends of the partition strictly inside the free area, split it.
    	            // printf("Splitting a free block.\n");
		    for (k=nBlocks; k>j; k--)	// Move the rest of the list right by 1 slot
			{
			pqwFirst[k] = pqwFirst[k-1];
			pqwLast[k] = pqwLast[k-1];
			}
		    nBlocks += 1;
		    pqwLast[j] = pPartEntry[iIndex].StartingLBA - qwOne;
		    pqwFirst[j+1] = pPartEntry[iIndex].EndingLBA + qwOne;
		    }
		else if (   (pqwFirst[j] == pPartEntry[iIndex].StartingLBA)
    	                 && (pPartEntry[iIndex].EndingLBA == pqwLast[j]) )
    	            {	// If both ends of the partition exactly match the free area, remove it.
    	            // printf("Removing one free block.\n");
    	            nBlocks -= 1;
		    for (k=j; k<nBlocks; k++)	// Move the rest of the list left by 1 slot
			{
			pqwFirst[k] = pqwFirst[k+1];
			pqwLast[k] = pqwLast[k+1];
			}
    	            }
    	        else if (pqwFirst[j] < pPartEntry[iIndex].StartingLBA)
    	            {	// If the ends match, mark the new end
    	            // printf("Shrinking a free block end.\n");
		    pqwLast[j] = pPartEntry[iIndex].StartingLBA - qwOne;
                    }
                else
                    {	// The beginnings match. Mark the new beginning
    	            // printf("Shrinking a free block start.\n");
		    pqwFirst[j] = pPartEntry[iIndex].EndingLBA + qwOne;
                    }
		/*
		printf("Free blocks: Sectors");
		for (k=0; k<nBlocks; k++) { printfx(" %s", pqwFirst[k]); printfx("-%s;", pqwLast[k]); }
		printf("\n");
	        */
		break;	// Operation done
    	        }
    	    }
    	}
	    	
    if (iNewPartition == -1)
        {
    	GptAllocSectorsFail(-1);
    	}

    // Allocate a block of sectors for our partition data.
    if (qwForceSect != qwZero)
        {
        qwFirst = qwForceSect;
	qwLast = qwFirst + qwNSect - qwOne;
        // Scan the free block list to make sure the whole requested range is free
        for (j=0; j<nBlocks; j++)
            {
            if ((pqwFirst[j] <= qwFirst) && (pqwLast[j] >= qwLast)) break;
            }
        if (j >= nBlocks) GptAllocSectorsFail(-5);
        }
    else    // Scan the free block list to find the smallest area large enough for our data.
        {
        QWORD qwMaxWidth = _QWORD(0xFFFFFFFF, 0xFFFFFFFF);
#ifdef _DEBUG
        if (iVerbose) printf("Free blocks: Sectors");
#endif
        for (j=0; j<nBlocks; j++)
            {
#ifdef _DEBUG
            if (iVerbose)  { printfx(" %s", pqwFirst[j]); printfx("-%s;", pqwLast[j]); }
#endif
            QWORD qwWidth = qwOne + pqwLast[j] - pqwFirst[j];
            if (   (qwWidth >= qwNSect)
                && (qwWidth < qwMaxWidth) 
               )
                {
                if (   (qwFirst == qwZero)
                    || (pqwFirst[j] != hGPT->pGptHdr->LastUsableLBA) 
                   )
                    {  // Allocate that block, except if it's the last one.
                    qwMaxWidth = qwWidth;
                    qwFirst = pqwFirst[j];
                    }
                }
            }
#ifdef _DEBUG
        if (iVerbose) printf("\n");
#endif
        if (!qwFirst) GptAllocSectorsFail(-2);
        }

    qwLast = qwFirst + qwNSect - qwOne;
#ifdef _DEBUG
    if (iVerbose) { printfx("Allocated sectors 0x%s", qwFirst); printfx(" to 0x%s.\n", qwLast); }
#endif
	    
    // Fill in the new partition characteristics
    memset(pNewEntry, 0, sizeof(EFI_PARTITION_ENTRY));
    pNewEntry->PartitionTypeGUID = guidHardDiskImage;		// Anything but 0 will do at this stage.
    uuid_create((uuid_t *)&(pNewEntry->UniquePartitionGUID)); 	// Generate a new GUID
    pNewEntry->StartingLBA = qwFirst;
    pNewEntry->EndingLBA = qwLast;

alloc_return:
    free(pqwFirst);
    free(pqwLast);
    free(pGptEntryBuf);

    return iNewPartition;
    }