static struct part_iter *pi_gpt_next(struct part_iter *iter) { const struct disk_gpt_part_entry *gpt_part = NULL; if (iter->status) goto bail; while (++iter->index0 < iter->sub.gpt.pe_count) { gpt_part = (const struct disk_gpt_part_entry *) (iter->data + iter->index0 * iter->sub.gpt.pe_size); if (notsane_gpt(iter)) { iter->status = PI_INSANE; goto bail; } if (!guid_is0(&gpt_part->type) || iter->stepall) break; } /* no more partitions ? */ if (iter->index0 == iter->sub.gpt.pe_count) { iter->status = PI_DONE; goto bail; } /* gpt_part is guaranteed to be valid here */ iter->index = iter->index0 + 1; iter->rawindex = iter->index0 + 1; iter->start_lba = gpt_part->lba_first; iter->length = gpt_part->lba_last - gpt_part->lba_first + 1; iter->record = (char *)gpt_part; memcpy(&iter->sub.gpt.part_guid, &gpt_part->uid, sizeof(struct guid)); gpt_conv_label(iter); #ifdef DEBUG disk_gpt_part_dump(gpt_part); #endif return iter; bail: return NULL; }
static int setup_handover(const struct part_iter *iter, struct data_area *data) { struct disk_dos_part_entry *ha; uint32_t synth_size = sizeof *ha; /* * we have to cover both non-iterated but otherwise properly detected * gpt/dos schemes as well as raw disks; checking index for 0 covers both */ if (iter->index == 0) { uint32_t len; /* RAW handover protocol */ ha = malloc(synth_size); if (!ha) { critm(); goto bail; } len = ~0u; if (iter->length < len) len = iter->length; lba2chs(&ha->start, &iter->di, 0, L2C_CADD); lba2chs(&ha->end, &iter->di, len - 1, L2C_CADD); ha->active_flag = 0x80; ha->ostype = 0xDA; /* "Non-FS Data", anything is good here though ... */ ha->start_lba = 0; ha->length = len; } else if (iter->type == typegpt) { uint32_t *plen; /* GPT handover protocol */ synth_size += sizeof *plen + iter->gpt.pe_size; ha = malloc(synth_size); if (!ha) { critm(); goto bail; } lba2chs(&ha->start, &iter->di, iter->abs_lba, L2C_CADD); lba2chs(&ha->end, &iter->di, iter->abs_lba + iter->length - 1, L2C_CADD); ha->active_flag = 0x80; ha->ostype = 0xED; /* All bits set by default */ ha->start_lba = ~0u; ha->length = ~0u; /* If these fit the precision, pass them on */ if (iter->abs_lba < ha->start_lba) ha->start_lba = iter->abs_lba; if (iter->length < ha->length) ha->length = iter->length; /* Next comes the GPT partition record length */ plen = (uint32_t *)(ha + 1); plen[0] = iter->gpt.pe_size; /* Next comes the GPT partition record copy */ memcpy(plen + 1, iter->record, plen[0]); #ifdef DEBUG dprintf("GPT handover:\n"); disk_dos_part_dump(ha); disk_gpt_part_dump((struct disk_gpt_part_entry *)(plen + 1)); #endif /* the only possible case left is dos scheme */ } else if (iter->type == typedos) { /* MBR handover protocol */ ha = malloc(synth_size); if (!ha) { critm(); goto bail; } memcpy(ha, iter->record, synth_size); /* make sure these match bios imaginations and are ebr agnostic */ lba2chs(&ha->start, &iter->di, iter->abs_lba, L2C_CADD); lba2chs(&ha->end, &iter->di, iter->abs_lba + iter->length - 1, L2C_CADD); ha->start_lba = iter->abs_lba; ha->length = iter->length; #ifdef DEBUG dprintf("MBR handover:\n"); disk_dos_part_dump(ha); #endif } else { /* shouldn't ever happen */ goto bail; } data->base = 0x7be; data->size = synth_size; data->data = (void *)ha; return 0; bail: return -1; }