Ejemplo n.º 1
0
static UINTN analyze(VOID)
{
    UINTN   i, detected_parttype;
    CHARN   *fsname;
    UINTN   status;

    new_mbr_part_count = 0;

    // determine correct MBR types for GPT partitions
    if (gpt_part_count == 0) {
        Print(L"Status: No GPT partitions defined, nothing to sync.\n");
        return 0;
    }
    for (i = 0; i < gpt_part_count; i++) {
        gpt_parts[i].mbr_type = gpt_parts[i].gpt_parttype->mbr_type;
        if (gpt_parts[i].gpt_parttype->kind == GPT_KIND_BASIC_DATA) {
            // Basic Data: need to look at data in the partition
            status = detect_mbrtype_fs(gpt_parts[i].start_lba, &detected_parttype, &fsname);
            if (status != 0)
               Print(L"Warning: Error %d when detecting filesystem type!\n", status);
            if (detected_parttype)
                gpt_parts[i].mbr_type = detected_parttype;
            else
                gpt_parts[i].mbr_type = 0x0b;  // fallback: FAT32
        }
        // NOTE: mbr_type may still be 0 if content detection fails for exotic GPT types or file systems
    } // for

    // generate the new table
    generate_hybrid_mbr();
    if (!should_rewrite())
       return EFI_ABORTED;

    // display table
    Print(L"\nProposed new MBR partition table:\n");
    Print(L" # A    Start LBA      End LBA  Type\n");
    for (i = 0; i < new_mbr_part_count; i++) {
        Print(L" %d %s %12lld %12lld  %02x  %s\n",
              new_mbr_parts[i].index + 1,
              new_mbr_parts[i].active ? STR("*") : STR(" "),
              new_mbr_parts[i].start_lba,
              new_mbr_parts[i].end_lba,
              new_mbr_parts[i].mbr_type,
              mbr_parttype_name(new_mbr_parts[i].mbr_type));
    }

    return 0;
} // UINTN analyze()
Ejemplo n.º 2
0
static UINTN analyze_part(UINT64 partlba)
{
    UINTN   status;
    UINTN   i;
    CHARN   *bootcodename;
    UINTN   parttype;
    CHARN   *fsname;
    
    if (partlba == 0)
        Print(L"\nMBR contents:\n");
    else
        Print(L"\nPartition at LBA %lld:\n", partlba);
    
    // detect boot code
    status = detect_bootcode(partlba, &bootcodename);
    if (status)
        return status;
    Print(L" Boot Code: %s\n", bootcodename);
    
    if (partlba == 0)
        return 0;   // short-circuit MBR analysis
    
    // detect file system
    status = detect_mbrtype_fs(partlba, &parttype, &fsname);
    if (status)
        return status;
    Print(L" File System: %s\n", fsname);
    
    // cross-reference with partition table
    for (i = 0; i < gpt_part_count; i++) {
        if (gpt_parts[i].start_lba == partlba) {
            Print(L" Listed in GPT as partition %d, type %s\n", i+1,
                  gpt_parts[i].gpt_parttype->name);
        }
    }
    for (i = 0; i < mbr_part_count; i++) {
        if (mbr_parts[i].start_lba == partlba) {
            Print(L" Listed in MBR as partition %d, type %02x  %s%s\n", i+1,
                  mbr_parts[i].mbr_type,
                  mbr_parttype_name(mbr_parts[i].mbr_type),
                  mbr_parts[i].active ? STR(", active") : STR(""));
        }
    }
    
    return 0;
}
Ejemplo n.º 3
0
static UINTN analyze(int optind, int argc, char **argv)
{
    UINTN   action;
    UINTN   i, k, count_active, detected_parttype;
    CHARN   *fsname;
    UINT64  min_start_lba, max_end_lba, block_count, last_disk_lba;
    UINTN   status;
    BOOLEAN have_esp;
    
    new_mbr_part_count = 0;
    
	block_count = get_disk_size();
	last_disk_lba = block_count - 1;
	if (block_count == 0) {
		error("can't retrieve disk size");
		return 1;
	}

    // determine correct MBR types for GPT partitions
    if (gpt_part_count == 0) {
        Print(L"Status: No GPT partitions defined, nothing to sync.\n");
        return 1;
    }
    have_esp = FALSE;
    for (i = 0; i < gpt_part_count; i++) {
        gpt_parts[i].mbr_type = gpt_parts[i].gpt_parttype->mbr_type;
        if (gpt_parts[i].gpt_parttype->kind == GPT_KIND_BASIC_DATA) {
            // Basic Data: need to look at data in the partition
            status = detect_mbrtype_fs(gpt_parts[i].start_lba, &detected_parttype, &fsname);
            if (detected_parttype)
                gpt_parts[i].mbr_type = detected_parttype;
            else
                gpt_parts[i].mbr_type = 0x0b;  // fallback: FAT32
        } else if (gpt_parts[i].mbr_type == 0xef) {
            // EFI System Partition: GNU parted can put this on any partition,
            // need to detect file systems
            status = detect_mbrtype_fs(gpt_parts[i].start_lba, &detected_parttype, &fsname);
            if (!have_esp && (detected_parttype == 0x01 || detected_parttype == 0x0e || detected_parttype == 0x0c))
                ;  // seems to be a legitimate ESP, don't change
            else if (detected_parttype)
                gpt_parts[i].mbr_type = detected_parttype;
            else if (have_esp)    // make sure there's no more than one ESP per disk
                gpt_parts[i].mbr_type = 0x83;  // fallback: Linux
        }
        // NOTE: mbr_type may still be 0 if content detection fails for exotic GPT types or file systems
        
        if (gpt_parts[i].mbr_type == 0xef)
            have_esp = TRUE;
    }
    
    // generate the new table
    
	new_mbr_part_count = 1;
	count_active = 0;
	
	if (! create_empty_mbr) {
		if (optind < argc) {
			for (i = optind; i < argc; i++) {
				char *separator, csep = 0;
				BOOLEAN active   = FALSE;
				UINT8 force_type = 0;
				separator = strchr (argv[i], '+');
				if (! separator)
					separator = strchr (argv[i], '-');
				if (separator)
				{
					csep = *separator;
					*separator = 0;
				}
			
				int part = atoi(argv[i]);
				if (part < 1 || part > gpt_part_count) {
					error("invalid argument '%s', partition number must be between 1-%d !", argv[i], gpt_part_count);
					return 1;
				}
				part--; // 0 base partition number
				if (csep == '+') {
					active = TRUE;
					count_active ++;
					if (count_active == 2) {
						error("only one partition can be active !");
						return 1;
					}
				}

				if (separator && *(separator + 1)) {
					char *str_type = separator + 1;
					if(xtoi (str_type, &force_type) != 0) {
						error("invalid hex type: %s !", str_type);
						return 1;
					}
				}
			
				// Check that a partition has not already enter
				for (k = 1; k < new_mbr_part_count; k++) {
					if (new_mbr_parts[k].start_lba == gpt_parts[part].start_lba ||
						new_mbr_parts[k].end_lba   == gpt_parts[part].end_lba ) {
							error("you already add partition %d !",part+1);
							return 1;
					}
				}
			
				add_gpt_partition_to_mbr(new_mbr_part_count, part, force_type, active);
				new_mbr_part_count++;
			}
		}
		else {
			// add other GPT partitions until the table is full
			// TODO: in the future, prioritize partitions by kind
			if (gpt_parts[0].mbr_type == 0xef)
				i = 1;
			else
				i = 0;
		
			for (; i < gpt_part_count && new_mbr_part_count < 4; i++) {
				add_gpt_partition_to_mbr(new_mbr_part_count, i, 0, FALSE);
        
				new_mbr_part_count++;
			}
		}
	}
	
	// get the first and last used lba
	if ( new_mbr_part_count == 1) { // Only one EFI Protective partition
		min_start_lba = max_end_lba  = last_disk_lba + 1; // Take whole disk
	}
	else {
		min_start_lba = new_mbr_parts[1].start_lba;
		max_end_lba   = new_mbr_parts[1].end_lba;
		for (k = 2; k < new_mbr_part_count; k++) {
			if (max_end_lba < new_mbr_parts[k].end_lba)
				max_end_lba = new_mbr_parts[k].end_lba;
			if (min_start_lba > new_mbr_parts[k].start_lba)
				min_start_lba = new_mbr_parts[k].start_lba;
		}
	}
	
	// Reserved last part if not used
	if (new_mbr_part_count < 4 && max_end_lba < last_disk_lba && fill_mbr) {
		new_mbr_parts[new_mbr_part_count].index = new_mbr_part_count;
		new_mbr_parts[new_mbr_part_count].start_lba = max_end_lba + 1;
		new_mbr_parts[new_mbr_part_count].end_lba   = last_disk_lba;
		new_mbr_parts[new_mbr_part_count].mbr_type  = 0xee; // another protective area
		new_mbr_parts[new_mbr_part_count].active    = FALSE;
		new_mbr_part_count ++;
	}
    
    // first entry: EFI Protective
    new_mbr_parts[0].index     = 0;
    new_mbr_parts[0].start_lba = 1;
    new_mbr_parts[0].end_lba   = min_start_lba - 1;
    new_mbr_parts[0].mbr_type  = 0xee;
        
	action = ACTION_NOP;

	// Check if we need to rewrite MBR
	for (i = 0; i < 4; i ++) {
		if (new_mbr_parts[i].index     != mbr_parts[i].index     ||
			new_mbr_parts[i].start_lba != mbr_parts[i].start_lba ||
			new_mbr_parts[i].end_lba   != mbr_parts[i].end_lba   ||
			new_mbr_parts[i].mbr_type  != mbr_parts[i].mbr_type  ||
			new_mbr_parts[i].active    != mbr_parts[i].active) {
			action = ACTION_REWRITE;
			break;
		}
	}
	
    if (action == ACTION_NOP) {
        Print(L"Status: Tables are synchronized, no need to sync.\n");
        return 1;
    }
	else {
        Print(L"Status: MBR table must be updated.\n");
    }
    
    // dump table
    Print(L"\nProposed new MBR partition table:\n");
    Print(L" # A    Start LBA      End LBA  Type\n");
    for (i = 0; i < new_mbr_part_count; i++) {
        Print(L" %d %s %12lld %12lld  %02x  %s\n",
              new_mbr_parts[i].index + 1,
              new_mbr_parts[i].active ? STR("*") : STR(" "),
              new_mbr_parts[i].start_lba,
              new_mbr_parts[i].end_lba,
              new_mbr_parts[i].mbr_type,
              mbr_parttype_name(new_mbr_parts[i].mbr_type));
    }
    
    return 0;
}
Ejemplo n.º 4
0
Archivo: lib.c Proyecto: MacNB/gptsync
UINTN read_mbr(VOID)
{
    UINTN               status;
    UINTN               i;
    BOOLEAN             used;
    MBR_PARTITION_INFO       *table;

    Print(L"\nCurrent MBR partition table:\n");

    // read MBR data
    status = read_sector(0, sector);
    if (status != 0)
        return status;

    // check for validity
    if (*((UINT16 *)(sector + 510)) != 0xaa55) {
        Print(L" No MBR partition table present!\n");
        return 1;
    }
    table = (MBR_PARTITION_INFO *)(sector + 446);
    for (i = 0; i < 4; i++) {
        if (table[i].flags != 0x00 && table[i].flags != 0x80) {
            Print(L" MBR partition table is invalid!\n");
            return 1;
        }
    }

    // check if used
    used = FALSE;
    for (i = 0; i < 4; i++) {
        if (table[i].start_lba > 0 && table[i].size > 0) {
            used = TRUE;
            break;
        }
    }
    if (!used) {
        Print(L" No partitions defined\n");
        return 0;
    }

    // dump current state & fill internal structures
    Print(L" # A    Start LBA      End LBA  Type\n");
    for (i = 0; i < 4; i++) {
        if (table[i].start_lba == 0 || table[i].size == 0)
            continue;

        mbr_parts[mbr_part_count].index     = i;
        mbr_parts[mbr_part_count].start_lba = (UINT64)table[i].start_lba;
        mbr_parts[mbr_part_count].end_lba   = (UINT64)table[i].start_lba + (UINT64)table[i].size - 1;
        mbr_parts[mbr_part_count].mbr_type  = table[i].type;
        mbr_parts[mbr_part_count].active    = (table[i].flags == 0x80) ? TRUE : FALSE;

        Print(L" %d %s %12lld %12lld  %02x  %s\n",
              mbr_parts[mbr_part_count].index + 1,
              mbr_parts[mbr_part_count].active ? STR("*") : STR(" "),
              mbr_parts[mbr_part_count].start_lba,
              mbr_parts[mbr_part_count].end_lba,
              mbr_parts[mbr_part_count].mbr_type,
              mbr_parttype_name(mbr_parts[mbr_part_count].mbr_type));

        mbr_part_count++;
    }

    return 0;
}