#include <string.h>
#include <stdlib.h>
#include "global.h"
#include "partition.h"
#include "misc.h"
#include "menu_command.h"
#include "menu_partition.h"
struct dk_map2 default_vtoc_map[NDKMAP] = {
{ V_ROOT, 0 },
{ V_SWAP, V_UNMNT },
{ V_BACKUP, V_UNMNT },
{ V_UNASSIGNED, 0 },
{ V_UNASSIGNED, 0 },
{ V_UNASSIGNED, 0 },
{ V_USR, 0 },
{ V_UNASSIGNED, 0 },
#if defined(_SUNOS_VTOC_16)
#if defined(i386)
{ V_BOOT, V_UNMNT },
{ V_ALTSCTR, 0 },
#else
#error No VTOC format defined.
#endif
{ V_UNASSIGNED, 0 },
{ V_UNASSIGNED, 0 },
{ V_UNASSIGNED, 0 },
{ V_UNASSIGNED, 0 },
{ V_UNASSIGNED, 0 },
{ V_UNASSIGNED, 0 },
#endif
};
static uint64_t
maxofN(struct dk_gpt *map)
{
uint64_t max;
uint64_t sec_no[2], start[2], size[2];
int i;
for (i = 0; i < map->efi_nparts - 1; i++) {
start[0] = map->efi_parts[i].p_start;
size[0] = map->efi_parts[i].p_size;
sec_no[0] = start[0] + size[0];
start[1] = map->efi_parts[i + 1].p_start;
size[1] = map->efi_parts[i + 1].p_size;
sec_no[1] = start[1] + size[1];
if (map->efi_parts[i].p_tag == V_BACKUP) {
sec_no[0] = 0;
}
if (map->efi_parts[i+1].p_tag == V_BACKUP) {
sec_no[1] = 0;
}
if (i == 0) {
max = sec_no[1];
}
if (sec_no[0] > max) {
max = sec_no[0];
} else {
max = max;
}
}
if (max == 0)
max = map->efi_first_u_lba;
return (max);
}
void
change_partition(int num)
{
uint_t i;
uint64_t i64, j64;
uint_t j;
int deflt;
part_deflt_t p_deflt;
u_ioparam_t ioparam;
int tag;
int flag;
char msg[256];
blkaddr32_t cyl_offset = 0;
efi_deflt_t efi_deflt;
if (cur_parts == NULL) {
err_print("Current Disk has no partition table.\n");
return;
}
if (cur_label == L_TYPE_EFI) {
if (num > cur_parts->etoc->efi_nparts - 1) {
err_print("Invalid partition for EFI label\n");
return;
}
print_efi_partition(cur_parts->etoc, num, 1);
fmt_print("\n");
deflt = cur_parts->etoc->efi_parts[num].p_tag;
if (deflt == V_UNASSIGNED) {
deflt = V_USR;
}
(void) sprintf(msg, "Enter partition id tag");
ioparam.io_slist = ptag_choices;
tag = input(FIO_SLIST, msg, ':', &ioparam, &deflt, DATA_INPUT);
deflt = cur_parts->etoc->efi_parts[num].p_flag;
(void) sprintf(msg, "Enter partition permission flags");
ioparam.io_slist = pflag_choices;
flag = input(FIO_SLIST, msg, ':', &ioparam, &deflt, DATA_INPUT);
ioparam.io_bounds.lower = cur_parts->etoc->efi_first_u_lba;
ioparam.io_bounds.upper = cur_parts->etoc->efi_last_u_lba;
efi_deflt.start_sector = maxofN(cur_parts->etoc);
if ((cur_parts->etoc->efi_parts[num].p_start != 0) &&
(cur_parts->etoc->efi_parts[num].p_size != 0)) {
efi_deflt.start_sector =
cur_parts->etoc->efi_parts[num].p_start;
}
efi_deflt.end_sector = ioparam.io_bounds.upper -
efi_deflt.start_sector;
i64 = input(FIO_INT64, "Enter new starting Sector", ':',
&ioparam, (int *)&efi_deflt, DATA_INPUT);
ioparam.io_bounds.lower = 0;
ioparam.io_bounds.upper = cur_parts->etoc->efi_last_u_lba;
efi_deflt.end_sector = cur_parts->etoc->efi_parts[num].p_size;
efi_deflt.start_sector = i64;
j64 = input(FIO_EFI, "Enter partition size", ':', &ioparam,
(int *)&efi_deflt, DATA_INPUT);
if (j64 == 0) {
tag = V_UNASSIGNED;
i64 = 0;
} else if ((j64 != 0) && (tag == V_UNASSIGNED)) {
tag = V_USR;
}
if (cur_parts->pinfo_name != NULL)
make_partition();
cur_parts->etoc->efi_parts[num].p_tag = tag;
cur_parts->etoc->efi_parts[num].p_flag = flag;
cur_parts->etoc->efi_parts[num].p_start = i64;
cur_parts->etoc->efi_parts[num].p_size = j64;
return;
}
print_partition(cur_parts, num, 1);
fmt_print("\n");
assert(cur_parts->vtoc.v_version == V_VERSION);
deflt = cur_parts->vtoc.v_part[num].p_tag;
(void) sprintf(msg, "Enter partition id tag");
ioparam.io_slist = ptag_choices;
tag = input(FIO_SLIST, msg, ':', &ioparam, &deflt, DATA_INPUT);
deflt = cur_parts->vtoc.v_part[num].p_flag;
(void) sprintf(msg, "Enter partition permission flags");
ioparam.io_slist = pflag_choices;
flag = input(FIO_SLIST, msg, ':', &ioparam, &deflt, DATA_INPUT);
#if defined(i386)
if (tag != V_UNASSIGNED && tag != V_BACKUP && tag != V_BOOT) {
cyl_offset = cur_parts->pinfo_map[I_PARTITION].dkl_cylno + 1;
if (tag != V_ALTSCTR) {
if (cur_parts->pinfo_map[J_PARTITION].dkl_nblk != 0) {
cyl_offset =
cur_parts->
pinfo_map[J_PARTITION].dkl_cylno +
((cur_parts->
pinfo_map[J_PARTITION].dkl_nblk +
(spc() - 1)) / spc());
}
}
}
#endif
ioparam.io_bounds.lower = 0;
ioparam.io_bounds.upper = ncyl - 1;
deflt = max(cur_parts->pinfo_map[num].dkl_cylno, cyl_offset);
i = (uint_t)input(FIO_INT, "Enter new starting cyl", ':', &ioparam,
&deflt, DATA_INPUT);
ioparam.io_bounds.lower = 0;
ioparam.io_bounds.upper = (ncyl - i) * spc();
p_deflt.start_cyl = i;
p_deflt.deflt_size = min(cur_parts->pinfo_map[num].dkl_nblk,
ioparam.io_bounds.upper);
j = (uint_t)input(FIO_ECYL, "Enter partition size", ':', &ioparam,
(int *)&p_deflt, DATA_INPUT);
if (j == 0) {
tag = V_UNASSIGNED;
i = 0;
}
#if defined(i386)
if (i < cyl_offset && tag != V_UNASSIGNED && tag != V_BACKUP &&
tag != V_BOOT) {
if (i < cur_parts->pinfo_map[I_PARTITION].dkl_cylno + 1) {
fmt_print("\nWarning: Partition overlaps boot ");
fmt_print("partition. Specify different start cyl.\n");
return;
}
if (i < cyl_offset) {
fmt_print("\nWarning: Partition overlaps alternates ");
fmt_print("partition. Specify different start cyl.\n");
return;
}
}
#endif
if (tag == V_BACKUP) {
uint_t fullsz;
fullsz = ncyl * nhead * nsect;
if (fullsz != j) {
fmt_print("\nWarning: Partition with V_BACKUP tag should ");
fmt_print("specify full disk capacity. \n");
return;
}
}
if (cur_parts->pinfo_name != NULL)
make_partition();
cur_parts->pinfo_map[num].dkl_cylno = i;
cur_parts->pinfo_map[num].dkl_nblk = j;
#if defined(_SUNOS_VTOC_16)
cur_parts->vtoc.v_part[num].p_start = (daddr_t)(i * (nhead * nsect));
cur_parts->vtoc.v_part[num].p_size = (long)j;
#endif
assert(cur_parts->vtoc.v_version == V_VERSION);
cur_parts->vtoc.v_part[num].p_tag = (ushort_t)tag;
cur_parts->vtoc.v_part[num].p_flag = (ushort_t)flag;
}
int
get_partition(void)
{
register struct partition_info *pptr;
register struct partition_info *parts;
parts = cur_dtype->dtype_plist;
if (parts == NULL) {
err_print("No defined partition tables.\n");
make_partition();
return (-1);
}
enter_critical();
for (pptr = parts; pptr != NULL; pptr = pptr->pinfo_next) {
if (cur_dtype->dtype_asciilabel) {
if (pptr->pinfo_name != NULL && strcmp(pptr->pinfo_name,
cur_dtype->dtype_asciilabel) == 0) {
cur_disk->disk_parts = cur_parts = pptr;
cur_parts->pinfo_name = pptr->pinfo_name;
exit_critical();
return (0);
}
}
}
cur_disk->disk_parts = cur_parts = cur_dtype->dtype_plist;
cur_parts->pinfo_name = parts->pinfo_name;
exit_critical();
return (0);
}
void
make_partition(void)
{
register struct partition_info *pptr, *parts;
int i;
enter_critical();
pptr = (struct partition_info *)zalloc(sizeof (struct partition_info));
parts = cur_dtype->dtype_plist;
if (parts == NULL) {
cur_dtype->dtype_plist = pptr;
} else {
while (parts->pinfo_next != NULL) {
parts = parts->pinfo_next;
}
parts->pinfo_next = pptr;
pptr->pinfo_next = NULL;
}
if (cur_label == L_TYPE_EFI) {
struct dk_gpt *map;
int nparts;
int size;
nparts = cur_parts->etoc->efi_nparts;
size = sizeof (struct dk_part) * nparts +
sizeof (struct dk_gpt);
map = zalloc(size);
(void) memcpy(map, cur_parts->etoc, size);
pptr->etoc = map;
cur_disk->disk_parts = cur_parts = pptr;
exit_critical();
return;
}
if (cur_parts != NULL) {
for (i = 0; i < NDKMAP; i++) {
pptr->pinfo_map[i] = cur_parts->pinfo_map[i];
}
pptr->vtoc = cur_parts->vtoc;
} else {
set_vtoc_defaults(pptr);
}
cur_disk->disk_parts = cur_parts = pptr;
exit_critical();
}
void
delete_partition(struct partition_info *parts)
{
struct partition_info *pptr;
if (cur_dtype->dtype_plist == NULL) {
err_print("Error: unexpected null partition list.\n");
fullabort();
}
if (cur_dtype->dtype_plist == parts)
cur_dtype->dtype_plist = parts->pinfo_next;
else {
for (pptr = cur_dtype->dtype_plist; pptr->pinfo_next != parts;
pptr = pptr->pinfo_next)
;
pptr->pinfo_next = parts->pinfo_next;
}
destroy_data((char *)parts);
}
void
set_vtoc_defaults(struct partition_info *part)
{
int i;
bzero((caddr_t)&part->vtoc, sizeof (struct dk_vtoc));
part->vtoc.v_version = V_VERSION;
part->vtoc.v_nparts = NDKMAP;
part->vtoc.v_sanity = VTOC_SANE;
for (i = 0; i < NDKMAP; i++) {
part->vtoc.v_part[i].p_tag = default_vtoc_map[i].p_tag;
part->vtoc.v_part[i].p_flag = default_vtoc_map[i].p_flag;
}
}