]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2003-01-03 Yoshinori K. Okuji <okuji@enbug.org>
authorokuji <okuji@localhost>
Thu, 2 Jan 2003 23:46:21 +0000 (23:46 +0000)
committerokuji <okuji@localhost>
Thu, 2 Jan 2003 23:46:21 +0000 (23:46 +0000)
* util/i386/pc/pupa-setup.c (setup): Define the internal
function find_first_partition_start at the top level, because GCC
3.0.x cannot compile internal functions in deeper scopes
correctly.
(find_root_device): Use lstat instead of stat.
Don't follow symbolic links.
Fix the path-constructing code.

* util/i386/pc/biosdisk.c [__linux__] (BLKFLSBUF): New macro.
(pupa_util_biosdisk_open) [__linux__]: Get the size of a device
by a BLKGETSIZE ioctl first, because block devices don't fill
the member st_mode of the structure stat on Linux.
[__linux__] (linux_find_partition): Use a temporary buffer
REAL_DEV for the working space. Copy it to DEV before returning.
(open_device) [__linux__]: Call ioctl with BLKFLSBUF to make the
buffer cache consistent.
(get_os_disk) [__linux__]: Use the length 5 instead of 4 for
strncmp. The previous value was merely wrong.
(pupa_util_biosdisk_get_pupa_dev): Use stat instead of lstat.

* fs/fat.c (pupa_fat_read_data): Shift 4 instead of 12 when the
FAT size is 12. The previous value was merely wrong.

* kern/main.c (pupa_main): Don't split the starting message from
newlines.

* kern/term.c (pupa_putchar): Put CR after LF instead of before
LF, because BIOS goes crazy about character attributes in this
case.

ChangeLog
NEWS
fs/fat.c
kern/i386/pc/startup.S
kern/main.c
kern/term.c
util/i386/pc/biosdisk.c
util/i386/pc/grub-setup.c

index 04132a1e102190292b883dd2e8c22c70b2bc822b..2b4e8264f952a80f62eba2d1b6b76d9ced0ce9d0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2003-01-03  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/pupa-setup.c (setup): Define the internal
+       function find_first_partition_start at the top level, because GCC
+       3.0.x cannot compile internal functions in deeper scopes
+       correctly.
+       (find_root_device): Use lstat instead of stat.
+       Don't follow symbolic links.
+       Fix the path-constructing code.
+
+       * util/i386/pc/biosdisk.c [__linux__] (BLKFLSBUF): New macro.
+       (pupa_util_biosdisk_open) [__linux__]: Get the size of a device
+       by a BLKGETSIZE ioctl first, because block devices don't fill
+       the member st_mode of the structure stat on Linux.
+       [__linux__] (linux_find_partition): Use a temporary buffer
+       REAL_DEV for the working space. Copy it to DEV before returning.
+       (open_device) [__linux__]: Call ioctl with BLKFLSBUF to make the
+       buffer cache consistent.
+       (get_os_disk) [__linux__]: Use the length 5 instead of 4 for
+       strncmp. The previous value was merely wrong.
+       (pupa_util_biosdisk_get_pupa_dev): Use stat instead of lstat.
+
+       * fs/fat.c (pupa_fat_read_data): Shift 4 instead of 12 when the
+       FAT size is 12. The previous value was merely wrong.
+
+       * kern/main.c (pupa_main): Don't split the starting message from
+       newlines.
+
+       * kern/term.c (pupa_putchar): Put CR after LF instead of before
+       LF, because BIOS goes crazy about character attributes in this
+       case.
+
 2003-01-03  Yoshinori K. Okuji  <okuji@enbug.org>
 
        * include/i386/pc/util/biosdisk.h: New file.
diff --git a/NEWS b/NEWS
index e026778a491cf7a603f3b2dbc775fe72822a5124..3944a66f0bb0fd40b71fb60439dcfb3632973970 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,9 @@ New in 0.7:
   care when writing assembly code. See the comments at the beginning of
   startup.S, for more details.
 
+* New utility, ``pupa-setup''. This sets up PUPA to make it bootable
+  from a real disk.
+
 New in 0.6 - 2002-12-27, Yoshinori K. Okuji:
 
 * The chainloader and the FAT filesystem are modularized.
index 1c8a05738e16719509864bf04ea6a4b647894228..045c04b6c0be3e8d586891a3c00ee62b4ffb12b8 100644 (file)
--- a/fs/fat.c
+++ b/fs/fat.c
@@ -156,7 +156,7 @@ pupa_fat_mount (pupa_disk_t disk)
   data = (struct pupa_fat_data *) pupa_malloc (sizeof (*data));
   if (! data)
     goto fail;
-  
+
   /* Read the BPB.  */
   if (pupa_disk_read (disk, 0, 0, sizeof (bpb), (char *) &bpb))
     goto fail;
@@ -437,19 +437,25 @@ pupa_fat_read_data (pupa_disk_t disk, struct pupa_fat_data *data,
              break;
            case 12:
              if (data->cur_cluster & 1)
-               next_cluster >>= 12;
+               next_cluster >>= 4;
              
              next_cluster &= 0x0FFF;
              break;
            }
 
+#if 0
+         pupa_printf ("%s:%d: fat_size=%d, next_cluster=%u\n",
+                      __FILE__, __LINE__, data->fat_size, next_cluster);
+#endif
+         
          /* Check the end.  */
          if (next_cluster >= data->cluster_eof_mark)
            return ret;
 
          if (next_cluster < 2 || next_cluster >= data->num_clusters)
            {
-             pupa_error (PUPA_ERR_BAD_FS, "invalid cluster");
+             pupa_error (PUPA_ERR_BAD_FS, "invalid cluster %u",
+                         next_cluster);
              return -1;
            }
 
index 5e6d55604a49fec59eb64bb399c8ce0bc46f9049..0fdc656812ba979cca835b59bcd4463d23404ae3 100644 (file)
@@ -991,8 +991,8 @@ FUNCTION(pupa_console_putchar)
        int     $0x10
 
        jmp     3f
-       
-1:     movb    $0x7, %bl
+
+1:     movw    $1, %bx
        movb    $0xe, %ah
        int     $0x10
        
@@ -1001,7 +1001,7 @@ FUNCTION(pupa_console_putchar)
        
        popa
        ret
-
+       
 
 /*
  * int pupa_console_getkey (void)
index 2862e52cbd85091ddb131e8b2f9d125923640362..256a084d3e7a92a7917d93adb9ed42efe91dfba7 100644 (file)
@@ -67,9 +67,8 @@ pupa_main (void)
 
   /* Hello.  */
   pupa_setcolorstate (PUPA_TERM_COLOR_HIGHLIGHT);
-  pupa_printf ("Welcome to PUPA!");
+  pupa_printf ("Welcome to PUPA!\n\n");
   pupa_setcolorstate (PUPA_TERM_COLOR_STANDARD);
-  pupa_printf ("\n\n");
 
   pupa_register_exported_symbols ();
   pupa_load_modules ();
index 509e5c8e19d72383cf0600857dbe45a0ebd5c41d..6082e389a89eba92010eea0c62430e49e2f6296d 100644 (file)
@@ -73,9 +73,7 @@ pupa_term_get_current (void)
 void
 pupa_putchar (int c)
 {
-  if (c == '\n')
-    pupa_putchar ('\r');
-  else if (c == '\t' && pupa_cur_term->getxy)
+  if (c == '\t' && pupa_cur_term->getxy)
     {
       int n;
 
@@ -87,6 +85,9 @@ pupa_putchar (int c)
     }
   
   (pupa_cur_term->putchar) (c);
+  
+  if (c == '\n')
+    pupa_putchar ('\r');
 }
 
 int
index 59495bacd35dfa6e0f2dc7148b8a12972ab006c2..9ad1e558bd39e3571ab8aa29b344a8ea7fcefc2e 100644 (file)
@@ -66,6 +66,9 @@ struct hd_geometry
   unsigned long start;
 };
 # endif /* ! HDIO_GETGEO */
+# ifndef BLKGETSIZE
+#  define BLKGETSIZE    _IO(0x12,96)    /* return device size */
+# endif /* ! BLKGETSIZE */
 # ifndef MAJOR
 #  ifndef MINORBITS
 #   define MINORBITS   8
@@ -165,7 +168,34 @@ pupa_util_biosdisk_open (const char *name, pupa_disk_t disk)
   disk->id = drive;
 
   /* Get the size.  */
-  if (lstat (map[drive], &st) < 0)
+#ifdef __linux__
+  {
+    unsigned long nr;
+    int fd;
+
+    fd = open (map[drive], O_RDONLY);
+    if (! fd)
+      return pupa_error (PUPA_ERR_BAD_DEVICE, "cannot open `%s'", map[drive]);
+
+    if (ioctl (fd, BLKGETSIZE, &nr))
+      {
+       close (fd);
+       goto fail;
+      }
+
+    close (fd);
+    disk->total_sectors = nr;
+    
+    pupa_util_info ("the size of %s is %lu", name, disk->total_sectors);
+    
+    return PUPA_ERR_NONE;
+  }
+#else
+# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
+#endif
+
+ fail:
+  if (stat (map[drive], &st) < 0)
     return pupa_error (PUPA_ERR_BAD_DEVICE, "cannot stat `%s'", map[drive]);
 
   if (st.st_blocks)
@@ -174,6 +204,8 @@ pupa_util_biosdisk_open (const char *name, pupa_disk_t disk)
     /* Hmm... Use st_size instead.  */
     disk->total_sectors = st.st_size >> PUPA_DISK_SECTOR_BITS;
   
+  pupa_util_info ("the size of %s is %lu", name, disk->total_sectors);
+  
   return PUPA_ERR_NONE;
 }
 
@@ -185,22 +217,25 @@ linux_find_partition (char *dev, unsigned long sector)
   const char *format;
   char *p;
   int i;
+  char *real_dev;
+
+  real_dev = xstrdup (dev);
   
-  if (have_devfs () && strcmp (dev + len - 5, "/disc") == 0)
+  if (have_devfs () && strcmp (real_dev + len - 5, "/disc") == 0)
     {
-      p = dev + len - 4;
+      p = real_dev + len - 4;
       format = "part%d";
     }
-  else if ((strncmp (dev + 5, "hd", 2) == 0
-           || strncmp (dev + 5, "sd", 2) == 0)
-          && dev[7] >= 'a' && dev[7] <= 'z')
+  else if ((strncmp (real_dev + 5, "hd", 2) == 0
+           || strncmp (real_dev + 5, "sd", 2) == 0)
+          && real_dev[7] >= 'a' && real_dev[7] <= 'z')
     {
-      p = dev + 8;
+      p = real_dev + 8;
       format = "%d";
     }
-  else if (strncmp (dev + 5, "rd/c", 4) == 0)
+  else if (strncmp (real_dev + 5, "rd/c", 4) == 0)
     {
-      p = strchr (dev + 9, 'd');
+      p = strchr (real_dev + 9, 'd');
       if (! p)
        return 0;
 
@@ -211,30 +246,42 @@ linux_find_partition (char *dev, unsigned long sector)
       format = "p%d";
     }
   else
-    return 0;
+    {
+      free (real_dev);
+      return 0;
+    }
 
-  for (i = 0; i < 10000; i++)
+  for (i = 1; i < 10000; i++)
     {
       int fd;
       struct hd_geometry hdg;
       
       sprintf (p, format, i);
-      fd = open (dev, O_RDONLY);
+      fd = open (real_dev, O_RDONLY);
       if (! fd)
-       return 0;
+       {
+         free (real_dev);
+         return 0;
+       }
 
       if (ioctl (fd, HDIO_GETGEO, &hdg))
        {
          close (fd);
+         free (real_dev);
          return 0;
        }
 
       close (fd);
       
       if (hdg.start == sector)
-       return 1;
+       {
+         strcpy (dev, real_dev);
+         free (real_dev);
+         return 1;
+       }
     }
 
+  free (real_dev);
   return 0;
 }
 #endif /* __linux__ */
@@ -266,12 +313,16 @@ open_device (const pupa_disk_t disk, unsigned long sector, int flags)
       is_partition = linux_find_partition (dev, disk->partition->start);
     
     /* Open the partition.  */
+    pupa_util_info ("opening the device `%s'", dev);
     fd = open (dev, flags);
     if (fd < 0)
       {
        pupa_error (PUPA_ERR_BAD_DEVICE, "cannot open `%s'", dev);
        return -1;
       }
+
+    /* Make the buffer cache consistent with the physical disk.  */
+    ioctl (fd, BLKFLSBUF, 0);
     
     if (is_partition)
       sector -= disk->partition->start;
@@ -560,9 +611,9 @@ get_os_disk (const char *os_dev)
   if (! realpath (os_dev, path))
     return 0;
   
-  if (strncmp ("/dev/", path, 4) == 0)
+  if (strncmp ("/dev/", path, 5) == 0)
     {
-      p = path + 4;
+      p = path + 5;
 
       if (have_devfs ())
        {
@@ -653,8 +704,8 @@ pupa_util_biosdisk_get_pupa_dev (const char *os_dev)
 {
   struct stat st;
   int drive;
-  
-  if (lstat (os_dev, &st) < 0)
+
+  if (stat (os_dev, &st) < 0)
     {
       pupa_error (PUPA_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
       return 0;
@@ -687,6 +738,14 @@ pupa_util_biosdisk_get_pupa_dev (const char *os_dev)
     
     int find_partition (const pupa_partition_t partition)
       {
+       if (partition->bsd_part < 0)
+         pupa_util_info ("DOS partition %d starts from %lu",
+                         partition->dos_part, partition->start);
+       else
+         pupa_util_info ("BSD partition %d,%c starts from %lu",
+                         partition->dos_part, partition->bsd_part + 'a',
+                         partition->start);
+       
        if (hdg.start == partition->start)
          {
            dos_part = partition->dos_part;
@@ -720,17 +779,25 @@ pupa_util_biosdisk_get_pupa_dev (const char *os_dev)
       }
     
     close (fd);
+
+    pupa_util_info ("%s starts from %lu", os_dev, hdg.start);
     
     if (hdg.start == 0)
       return name;
-    
+
+    pupa_util_info ("opening the device %s", name);
     disk = pupa_disk_open (name);
     free (name);
     
     if (! disk)
       return 0;
     
-    pupa_partition_iterate (disk, find_partition);
+    if (pupa_partition_iterate (disk, find_partition) != PUPA_ERR_NONE)
+      {
+       pupa_disk_close (disk);
+       return 0;
+      }
+    
     if (dos_part < 0)
       {
        pupa_disk_close (disk);
index 7c4390b0c866ddcfe693b48f5f4b29bd20dcbe1a..b4b123c44aea050d2662d2890c9b6be5e521e295 100644 (file)
@@ -82,12 +82,25 @@ setup (const char *prefix, const char *dir,
   pupa_uint16_t last_length = PUPA_DISK_SECTOR_SIZE;
   pupa_file_t file;
   FILE *fp;
+  unsigned long first_start = ~0UL;
   
   auto void save_first_sector (unsigned long sector, unsigned offset,
                               unsigned length);
   auto void save_blocklists (unsigned long sector, unsigned offset,
                             unsigned length);
 
+  auto int find_first_partition_start (const pupa_partition_t p);
+  
+  int find_first_partition_start (const pupa_partition_t p)
+    {
+      if (! pupa_partition_is_empty (p->dos_type)
+         && ! pupa_partition_is_bsd (p->dos_type)
+         && first_start > p->start)
+       first_start = p->start;
+      
+      return 0;
+    }
+  
   void save_first_sector (unsigned long sector, unsigned offset,
                          unsigned length)
     {
@@ -195,23 +208,10 @@ setup (const char *prefix, const char *dir,
      try to embed the core image into after the MBR.  */
   if (dest_dev->disk->has_partitions && ! dest_dev->disk->partition)
     {
-      auto int find_first_partition_start (const pupa_partition_t p);
-      unsigned long first_sector = ~0UL;
-      
-      int find_first_partition_start (const pupa_partition_t p)
-       {
-         if (! pupa_partition_is_empty (p->dos_type)
-             && ! pupa_partition_is_bsd (p->dos_type)
-             && first_sector > p->start)
-           first_sector = p->start;
-
-         return 0;
-       }
-
       pupa_partition_iterate (dest_dev->disk, find_first_partition_start);
 
       /* If there is enough space...  */
-      if ((unsigned long) core_sectors + 1 <= first_sector)
+      if ((unsigned long) core_sectors + 1 <= first_start)
        {
          pupa_util_info ("will embed the core image into after the MBR");
          
@@ -277,7 +277,28 @@ setup (const char *prefix, const char *dir,
            pupa_util_info ("succeeded in opening the core image but cannot read %d bytes",
                            (int) core_size);
          else if (memcmp (core_img, tmp_img, core_size) != 0)
-           pupa_util_info ("succeeded in opening the core image but the data is different");
+           {
+#if 0
+             FILE *dump;
+             FILE *dump2;
+             
+             dump = fopen ("dump.img", "wb");
+             if (dump)
+               {
+                 fwrite (tmp_img, 1, core_size, dump);
+                 fclose (dump);
+               }
+
+             dump2 = fopen ("dump2.img", "wb");
+             if (dump2)
+               {
+                 fwrite (core_img, 1, core_size, dump2);
+                 fclose (dump2);
+               }
+             
+#endif      
+             pupa_util_info ("succeeded in opening the core image but the data is different");
+           }
          else
            {
              pupa_file_close (file);
@@ -288,6 +309,9 @@ setup (const char *prefix, const char *dir,
        }
       else
        pupa_util_info ("couldn't open the core image");
+
+      if (pupa_errno)
+       pupa_util_info ("error message = %s", pupa_errmsg);
       
       pupa_errno = PUPA_ERR_NONE;
       sync ();
@@ -530,6 +554,7 @@ find_root_device (const char *dir, dev_t dev)
 
   saved_cwd = xgetcwd ();
 
+  pupa_util_info ("changing current directory to %s", dir);
   if (chdir (dir) < 0)
     {
       free (saved_cwd);
@@ -544,10 +569,14 @@ find_root_device (const char *dir, dev_t dev)
       if (strcmp (ent->d_name, ".") == 0 || strcmp (ent->d_name, "..") == 0)
        continue;
 
-      if (stat (ent->d_name, &st) < 0)
+      if (lstat (ent->d_name, &st) < 0)
        /* Ignore any error.  */
        continue;
 
+      if (S_ISLNK (st.st_mode))
+       /* Don't follow symbolic links.  */
+       continue;
+      
       if (S_ISDIR (st.st_mode))
        {
          /* Find it recursively.  */
@@ -570,11 +599,13 @@ find_root_device (const char *dir, dev_t dev)
        {
          /* Found!  */
          char *res;
+         char *cwd;
 
-         res = xmalloc (strlen (saved_cwd) + strlen (dir)
-                        + strlen (ent->d_name) + 3);
-         sprintf (res, "%s/%s/%s", saved_cwd, dir, ent->d_name);
+         cwd = xgetcwd ();
+         res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 2);
+         sprintf (res, "%s/%s", cwd, ent->d_name);
          strip_extra_slashes (res);
+         free (cwd);
 
          if (chdir (saved_cwd) < 0)
            pupa_util_error ("Cannot restore the original directory");
@@ -731,6 +762,8 @@ main (int argc, char *argv[])
       root_dev = guess_root_device (dir ? : DEFAULT_DIRECTORY);
       if (! root_dev)
        {
+         pupa_util_info ("guessing the root device failed, because of `%s'",
+                         pupa_errmsg);
          pupa_util_error ("Cannot guess the root device. Specify the option ``--root-device''.");
        }
     }