Hello,

I was longer time looking for decent bootmanager which allows me to boot
as many operating systems as I need. I am developing sevral open source
programms, so I want to be able to test it at least on *BSD, linux,
solaris and win32. It is six systems. Five of those need to be installed
in primary partition to be able to install and boot. So it is impossible
to boot all those systems to have it on one disk.
I invented one dirty trick which will allow me to do so. The idea is to
map logical disks from extended partion to one entry in primary partition.
It should make some partitioning programs unhappy because of overlapping
partitions on a disk, but is working perfectly. The only system I was not
able to install this way was Solaris 7 for noncommercial use because it is
doing too much sanity checks during installation.
At first I made one small linux programm which is doing that. But it is
painfull to boot eache times linux before booting any of such installed
OS's.
So last month I was have evaluated sevral bootmanagers and tryied to
implement my idea into some of them. I mostly failed because I am quite
poor asm programmer and most of bootmanagers is writen in assembly code.
And with lilo I gave up after few attempts to get it working.
Last friday I found GRUB on freshmeat and I was impressed with its
posibilities ... and I liked the way it works. So I added new command
"partmap" which is doing mapping logical disks from extended partition to
primary partition. And also new command "partid" which changes type of
partition. 

syntax of of this new commands :

partmap (hd0,2) (hd0,11)

it will map logical partition 12 to primary partiton 3 .

partid (hd0,11) 0xb

will change type of partition to 0xb (FAT 32)

Maybe also other people will be interested to use posibilities of this new
commands. So the attached file is unified diff again released version
grub-0.5.95 . I will appreciate any comments on this and I will very
appreciate if my patch sholud be added to grub.

Best regards,
Stevo.

-- 
Stefan Ondrejicka <[EMAIL PROTECTED]>
Beethovenova 11, 917 08 Trnava, Slovakia
http://www.idata.sk/~ondrej/
diff -ruN grub-0.5.95/stage2/builtins.c grub/stage2/builtins.c
--- grub-0.5.95/stage2/builtins.c       Thu Jun  1 08:26:52 2000
+++ grub/stage2/builtins.c      Sun Jul 23 15:21:37 2000
@@ -3063,6 +3063,40 @@
 };
 
 
+/* partmap */
+static int
+partmap_func (char *arg, int flags)
+{
+  return map_partitons(arg);
+}
+
+static struct builtin builtin_partmap =
+{
+   "partmap",
+   partmap_func,
+   BUILTIN_CMDLINE | BUILTIN_MENU,
+   "partmap PARTITION1 PARTITION2",
+   "Map logical partiton PARTITION2 to primary partition PARTITION1"
+};
+
+
+/* partmap */
+static int
+partid_func (char *arg, int flags)
+{
+  return set_partition_type(arg);
+}
+
+static struct builtin builtin_partid =
+{
+   "partid",
+   partid_func,
+   BUILTIN_CMDLINE | BUILTIN_MENU,
+   "partid PARTITION ID",
+   "Change PARTITION type to ID."
+};
+
+
 /* The table of builtin commands. Sorted in dictionary order.  */
 struct builtin *builtin_table[] =
 {
@@ -3096,6 +3130,8 @@
   &builtin_map,
   &builtin_module,
   &builtin_modulenounzip,
+  &builtin_partid,
+  &builtin_partmap,
   &builtin_password,
   &builtin_pause,
   &builtin_quit,
diff -ruN grub-0.5.95/stage2/disk_io.c grub/stage2/disk_io.c
--- grub-0.5.95/stage2/disk_io.c        Wed Apr 19 22:34:28 2000
+++ grub/stage2/disk_io.c       Sun Jul 23 16:41:21 2000
@@ -1520,3 +1520,414 @@
   if (fsys_table[fsys_type].close_func != 0)
     (*(fsys_table[fsys_type].close_func)) ();
 }
+
+
+static int
+parse_partitionstr(char *arg, int *disk_no, int *part_no)
+{
+  int nr;
+  char *p;
+  int foundnr;
+
+  p = arg;
+  while (*p == ' ') p++;
+
+  if (p[0] != '(' || p[1] != 'h' || p[2] != 'd')
+    return -1;
+  else
+      p += 3;
+
+  foundnr = 0;
+  nr = 0;
+  while (*p <= '9' && *p >= '0')
+  {
+    nr = nr * 10 + (*p - '0');
+    p++;
+    foundnr = 1;
+  }
+  if (foundnr)
+    *disk_no = nr;
+  else
+    return -1;
+
+  if (*p != ',')
+    return -1;
+  else
+    p++;
+  
+  foundnr = 0;
+  nr = 0;
+  while (*p <= '9' && *p >= '0')
+  {
+    nr = nr * 10 + (*p - '0');
+    p++;
+    foundnr = 1;
+  }
+  if (foundnr)
+    *part_no = nr;
+  else
+    return -1;
+
+  if (*p != ')')
+    return -1;
+  else
+    p++;
+
+  return p-arg;
+}
+
+struct partinfo {
+       unsigned char boot_ind;         /* 0x80 - active */
+       unsigned char head;             /* starting head */
+       unsigned char sector;           /* starting sector */
+       unsigned char cyl;              /* starting cylinder */
+       unsigned char sys_ind;          /* What partition type */
+       unsigned char end_head;         /* end head */
+       unsigned char end_sector;       /* end sector */
+       unsigned char end_cyl;          /* end cylinder */
+       unsigned int start_sect;        /* starting sector counting from 0 */
+       unsigned int nr_sects;          /* nr of sectors in partition */
+       unsigned int part_off;          /* real offset of partition */
+};
+
+static int
+get_ext_pt(unsigned int drive, unsigned int id, unsigned int ssec, unsigned int off, 
+int *l_num, struct partinfo *part)
+{
+  char l_block[SECTOR_SIZE];
+  int i;
+  int rv = -1;
+
+  /* Read the logical partition block. */
+  if (!rawread(drive, ssec + off, 0, SECTOR_SIZE, l_block))
+    return -1;
+
+  if (!PC_MBR_CHECK_SIG(l_block))
+  {
+    errnum = ERR_BAD_PART_TABLE;
+    return -1;
+  }
+
+  for(i = 0 ; i < PC_SLICE_MAX ; i++)
+  {
+    if (PC_SLICE_TYPE(l_block, i) == PC_SLICE_TYPE_NONE)
+      continue;
+
+    if (IS_PC_SLICE_TYPE_EXTENDED(PC_SLICE_TYPE(l_block, i)))
+    {
+      rv = get_ext_pt(drive, id, ssec, PC_SLICE_START(l_block, i), l_num, part);
+      if (rv == 0)
+       break;
+    }
+    else
+    {
+      if (*l_num == id)
+      {
+       part->boot_ind = PC_SLICE_FLAG(l_block, i);
+       part->head = PC_SLICE_HEAD(l_block, i);
+       part->sector = PC_SLICE_SEC(l_block, i);
+       part->cyl = PC_SLICE_CYL(l_block, i);
+       part->sys_ind = PC_SLICE_TYPE(l_block, i);
+       part->end_head = PC_SLICE_EHEAD(l_block, i);
+       part->end_sector = PC_SLICE_ESEC(l_block, i);
+       part->end_cyl = PC_SLICE_ECYL(l_block, i);
+       part->start_sect = PC_SLICE_START(l_block, i);
+       part->nr_sects = PC_SLICE_LENGTH(l_block, i);
+       part->part_off = ssec + off + PC_SLICE_START(l_block, i);
+
+        return 0;
+      }
+      (*l_num)++;
+    }
+  }
+
+  return rv;
+}
+
+int
+map_partitons (char *arg)
+{
+  int pdrive,ldrive;
+  int ppart,lpart;
+  int rv;
+  int ppart_nr,lpart_nr;
+  struct partinfo l_info;
+  char *mbr_block;
+
+  /* first parse arg */
+  rv = parse_partitionstr(arg, &pdrive, &ppart);
+  if (rv < 0)
+  {
+    errnum = ERR_DEV_FORMAT;
+    return -1;
+  }
+  if (arg[rv] != ' ')
+  {
+    errnum = ERR_BAD_ARGUMENT;
+    return -1;
+  }
+  rv = parse_partitionstr(arg+rv+1, &ldrive, &lpart);
+  if (rv < 0)
+  {
+    errnum = ERR_DEV_FORMAT;
+    return -1;
+  }
+
+  if (ldrive != pdrive)
+  {
+    grub_printf("Unable to map partitions cross disks\n");
+    errnum = ERR_BAD_ARGUMENT;
+    return -1;
+  }
+
+  if (ppart < 0 || ppart > 3)
+  {
+    grub_printf("First partition must be primary partition\n");
+    errnum = ERR_BAD_ARGUMENT;
+    return -1;
+  }
+
+  if (lpart < 4)
+  {
+    grub_printf("Second partition must be logical partition\n");
+    errnum = ERR_BAD_ARGUMENT;
+    return -1;
+  }
+
+  pdrive += 0x80;
+  /* check if drive is present and get its geometry */
+  if (buf_drive != pdrive)
+  {
+    if (get_diskinfo(pdrive, &buf_geom))
+    {
+      errnum = ERR_NO_DISK;
+      return -1;
+    }
+    buf_drive = pdrive;
+    buf_track = -1;
+  }
+
+  /* Read the MBR block.  */
+  if (!rawread(pdrive, 0, 0, SECTOR_SIZE, (char *) SCRATCHADDR))
+    return 0;
+
+  mbr_block = (char *) SCRATCHADDR;
+  if (!PC_MBR_CHECK_SIG(mbr_block))
+  {
+    errnum = ERR_BAD_PART_TABLE;
+    return -1;
+  }
+
+  lpart_nr = 4;
+  
+  for (ppart_nr = 0; ppart_nr < PC_SLICE_MAX; ppart_nr++)
+  {
+    if (PC_SLICE_TYPE(mbr_block, ppart_nr) == PC_SLICE_TYPE_NONE)
+      continue;
+
+
+    if (IS_PC_SLICE_TYPE_EXTENDED(PC_SLICE_TYPE(mbr_block, ppart_nr)))
+    {
+      rv = get_ext_pt(pdrive, lpart, PC_SLICE_START(mbr_block, ppart_nr), 0, 
+&lpart_nr, &l_info);
+    }
+  }
+
+  if (rv)
+  {
+    errnum = ERR_NO_PART;
+    return -1;
+  }
+
+  /* Reread the MBR block.  */
+  if (!rawread(pdrive, 0, 0, SECTOR_SIZE, (char *) SCRATCHADDR))
+    return -1;
+  mbr_block = (char *) SCRATCHADDR;
+
+#if 0
+  grub_printf("Pimary(%d) - (0x%x) - Start(%d) - Size(%d)\n",
+       ppart, PC_SLICE_TYPE(mbr_block, ppart), 
+       PC_SLICE_START(mbr_block, ppart), 
+       PC_SLICE_LENGTH(mbr_block, ppart));
+
+  grub_printf("Logical(%d) - (0x%x) - Start(%d) - Size(%d)\n",
+       lpart, l_info.sys_ind, l_info.part_off, l_info.nr_sects);
+#endif
+
+  PC_SLICE_FLAG(mbr_block, ppart) = l_info.boot_ind;
+  PC_SLICE_HEAD(mbr_block, ppart) = l_info.head;
+  PC_SLICE_SEC(mbr_block, ppart) = l_info.sector;
+  PC_SLICE_CYL(mbr_block, ppart) = l_info.cyl;
+  PC_SLICE_TYPE(mbr_block, ppart) = l_info.sys_ind;
+  PC_SLICE_EHEAD(mbr_block, ppart) = l_info.end_head;
+  PC_SLICE_ESEC(mbr_block, ppart) = l_info.end_sector;
+  PC_SLICE_ECYL(mbr_block, ppart) = l_info.end_cyl;
+  PC_SLICE_START(mbr_block, ppart) = l_info.part_off;
+  PC_SLICE_LENGTH(mbr_block, ppart) = l_info.nr_sects;
+
+#if 0
+  grub_printf("Pimary(%d) - (0x%x) - Start(%d) - Size(%d)\n",
+       ppart, PC_SLICE_TYPE(mbr_block, ppart), 
+       PC_SLICE_START(mbr_block, ppart), 
+       PC_SLICE_LENGTH(mbr_block, ppart));
+#endif
+
+  /* Write back the MBR.  */
+  buf_track = -1;
+  if (biosdisk (BIOSDISK_WRITE, pdrive, &buf_geom, 0, 1, SCRATCHSEG))
+  {
+    errnum = ERR_WRITE;
+    return -1;
+  }
+
+  return 0;
+}
+
+static int
+parse_xd_num(char *arg, int *num)
+{
+  char *p = arg;
+  int base = 10;
+  int nr = 0;
+  int foundnr = 0;
+
+  while (*p == ' ') p++;
+
+  if (p[0] == '0' && p[1] == 'x')
+  {
+    base = 16;
+    p += 2;
+  }
+  else
+    base = 10;
+
+  while ((*p >= '0' && *p <= '9' && (base == 10)) ||
+        ((base == 16) && ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p 
+>= 'A' && *p <= 'F'))))
+  {
+    int dig;
+
+    dig = *p - '0';
+    if (dig > 9)
+    {
+      dig = 10 + *p - 'A';
+
+      if (dig > 0xE)
+        dig = 10 + *p - 'a';
+    }
+
+    nr = dig + base * nr;
+    foundnr = 1;
+    p++;
+  }
+
+  if (!foundnr)
+     return -1;
+
+  if (*p != ' ' && *p != '\0')
+    return -1;
+ 
+  *num = nr;
+
+  return p-arg;
+}
+
+static int
+real_set_partition_type(unsigned int drive, unsigned int id, unsigned int ssec, 
+unsigned int off, int *l_num, int type)
+{
+  int i;
+  int rv = -1;
+  char *l_block = (char *) SCRATCHADDR;
+  int wasl = 1;
+
+  for(i = 0 ; i < PC_SLICE_MAX ; i++)
+  {
+    if (wasl)
+    {
+      /* Read the logical partition block. */
+      if (!rawread(drive, ssec + off, 0, SECTOR_SIZE, (char *) SCRATCHADDR))
+        return -1;
+      l_block = (char *) SCRATCHADDR;
+
+      if (!PC_MBR_CHECK_SIG(l_block))
+      {
+        errnum = ERR_BAD_PART_TABLE;
+        return -1;
+      }
+      wasl = 0;
+    }
+
+    if (PC_SLICE_TYPE(l_block, i) == PC_SLICE_TYPE_NONE)
+      continue;
+
+    if (IS_PC_SLICE_TYPE_EXTENDED(PC_SLICE_TYPE(l_block, i)))
+    {
+      wasl = 1;
+      rv = real_set_partition_type(drive, id, ssec ? ssec : PC_SLICE_START(l_block, 
+i), ssec ? PC_SLICE_START(l_block, i) : 0, l_num, type);
+      if (rv == 0)
+       break;
+    }
+    else
+    {
+      if ((ssec && (*l_num == id)) || (!ssec && i == id))
+      {
+        PC_SLICE_TYPE(l_block, i) = type;
+
+        /* Write back.  */
+        buf_track = -1;
+        if (biosdisk (BIOSDISK_WRITE, drive, &buf_geom, ssec+off, 1, SCRATCHSEG))
+        {
+          errnum = ERR_WRITE;
+          return -1;
+        }
+        return 0;
+      }
+      if (ssec)
+        (*l_num)++;
+    }
+  }
+
+  return rv;
+}
+
+int
+set_partition_type (char *arg)
+{
+  int drive;
+  int part;
+  int rv;
+  int id;
+  int l_num = 4;
+
+  /* first parse arg */
+  rv = parse_partitionstr(arg, &drive, &part);
+  if (rv < 0)
+  {
+    errnum = ERR_DEV_FORMAT;
+    return -1;
+  }
+  if (arg[rv] != ' ')
+  {
+    errnum = ERR_BAD_ARGUMENT;
+    return -1;
+  }
+  rv = parse_xd_num(arg+rv+1, &id);
+  if (rv < 0 || id > 0xFF)
+  {
+    errnum = ERR_BAD_ARGUMENT;
+    return -1;
+  }
+
+  drive += 0x80;
+  /* check if drive is present and get its geometry */
+  if (buf_drive != drive)
+  {
+    if (get_diskinfo(drive, &buf_geom))
+    {
+      errnum = ERR_NO_DISK;
+      return -1;
+    }
+    buf_drive = drive;
+    buf_track = -1;
+  }
+
+  return real_set_partition_type(drive, part, 0, 0, &l_num, id);
+} 
+

Reply via email to