]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2004-02-15 Jeroen Dekkers <jeroen@dekkers.cx>
authorjeroen <jeroen@localhost>
Sun, 15 Feb 2004 10:09:11 +0000 (10:09 +0000)
committerjeroen <jeroen@localhost>
Sun, 15 Feb 2004 10:09:11 +0000 (10:09 +0000)
* fs/ext2.c (pupa_ext2_read_file): Correct the value of BLOCKEND
when it is EXT2_BLOCK_SIZE (data).  New argument READ_HOOK, all
callers changed.  Set DATA->DISK->READ_HOOK to READ_HOOK before
reading and reset it after reading.
(pupa_ext2_close): Return PUPA_ERR_NONE.

* include/pupa/i386/pc/linux.h (PUPA_LINUX_INITRD_MAX_ADDRESS):
Correct value.
(struct linux_kernel_header): Add kernel_version and
initrd_addr_max.
* loader/i386/pc/linux.c (pupa_rescue_cmd_linux): Check whether
pupa_file_read succeeds.
(pupa_rescue_cmd_initrd): Implement.

ChangeLog
fs/ext2.c
include/grub/i386/pc/linux.h
loader/i386/pc/linux.c

index 8a0c70d5c1b3eb56d268e7bf07da5c9b10ccdc08..e42b879fec8bc4ad3b12d50c5c907a7b2c7c44d5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2004-02-15  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * fs/ext2.c (pupa_ext2_read_file): Correct the value of BLOCKEND
+       when it is EXT2_BLOCK_SIZE (data).  New argument READ_HOOK, all
+       callers changed.  Set DATA->DISK->READ_HOOK to READ_HOOK before
+       reading and reset it after reading.
+       (pupa_ext2_close): Return PUPA_ERR_NONE.
+
+       * include/pupa/i386/pc/linux.h (PUPA_LINUX_INITRD_MAX_ADDRESS):
+       Correct value.
+       (struct linux_kernel_header): Add kernel_version and
+       initrd_addr_max.
+       * loader/i386/pc/linux.c (pupa_rescue_cmd_linux): Check whether
+       pupa_file_read succeeds.
+       (pupa_rescue_cmd_initrd): Implement.
+
 2003-12-03  Marco Gerards  <metgerards@student.han.nl>
 
        * fs/ext2.c (pupa_ext2_label): New function.
index 9f1cca24f8f214098ce28fac6c37b06ed99a6043..62e46ef3df76265d0c2f4385a5a96a64d16de252 100644 (file)
--- a/fs/ext2.c
+++ b/fs/ext2.c
@@ -1,6 +1,7 @@
 /* ext2.c - Second Extended filesystem */
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2004  Free Software Foundation, Inc.
  *  Copyright (C) 2003  Marco Gerards <metgerards@student.han.nl>.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -235,8 +236,10 @@ pupa_ext2_get_file_block (struct pupa_ext2_data *data,
 /* Read LEN bytes from the file described by DATA starting with byte
    POS.  Return the amount of read bytes in READ.  */
 static pupa_ssize_t
-pupa_ext2_read_file (struct pupa_ext2_data *data, int pos,
-                    unsigned int len, char *buf)
+pupa_ext2_read_file (struct pupa_ext2_data *data,
+                    void (*read_hook) (unsigned long sector,
+                                       unsigned offset, unsigned length),
+                    int pos, unsigned int len, char *buf)
 {
   int i;
   int blockcnt;
@@ -264,7 +267,13 @@ pupa_ext2_read_file (struct pupa_ext2_data *data, int pos,
 
       /* Last block.  */
       if (i == blockcnt - 1)
-       blockend = (len + pos) % EXT2_BLOCK_SIZE (data);
+       {
+         blockend = (len + pos) % EXT2_BLOCK_SIZE (data);
+         
+         /* The last portion is exactly EXT2_BLOCK_SIZE (data).  */
+         if (!blockend)
+           blockend = EXT2_BLOCK_SIZE (data);
+       }
 
       /* First block.  */
       if (i == pos / EXT2_BLOCK_SIZE (data))
@@ -277,8 +286,10 @@ pupa_ext2_read_file (struct pupa_ext2_data *data, int pos,
         is zero filled instead.  */
       if (blknr)
        {
+         data->disk->read_hook = read_hook;      
          pupa_disk_read (data->disk, blknr, skipfirst,
-                               blockend, buf);
+                         blockend, buf);
+         data->disk->read_hook = 0;
          if (pupa_errno)
            return -1;
        }
@@ -418,7 +429,7 @@ pupa_ext2_find_file (struct pupa_ext2_data *data, const char *path, int *ino)
          struct ext2_dirent dirent;
 
          /* Read the directory entry.  */
-         pupa_ext2_read_file (data, fpos, sizeof (struct ext2_dirent),
+         pupa_ext2_read_file (data, 0, fpos, sizeof (struct ext2_dirent),
                               (char *) &dirent);
          if (pupa_errno)
            goto fail;
@@ -428,7 +439,7 @@ pupa_ext2_find_file (struct pupa_ext2_data *data, const char *path, int *ino)
              char filename[dirent.namelen + 1];
 
              /* Read the filename part of this directory entry.  */
-             pupa_ext2_read_file (data, fpos 
+             pupa_ext2_read_file (data, 0, fpos 
                                   + sizeof (struct ext2_dirent),
                                   dirent.namelen, filename);
              if (pupa_errno)
@@ -468,7 +479,7 @@ pupa_ext2_find_file (struct pupa_ext2_data *data, const char *path, int *ino)
                                      pupa_le_to_cpu32 (inode->size));
                      else
                        {
-                         pupa_ext2_read_file (data, 0, 
+                         pupa_ext2_read_file (data, 0, 0,
                                               pupa_le_to_cpu32 (inode->size),
                                               symlink);
                          if (pupa_errno)
@@ -604,7 +615,7 @@ pupa_ext2_close (pupa_file_t file)
   pupa_dl_unref (my_mod);
 #endif
 
-  return pupa_errno;
+  return PUPA_ERR_NONE;
 }
 
 /* Read LEN bytes data from FILE into BUF.  */
@@ -614,7 +625,7 @@ pupa_ext2_read (pupa_file_t file, char *buf, pupa_ssize_t len)
   struct pupa_ext2_data *data = 
     (struct pupa_ext2_data *) file->data;
   
-  return pupa_ext2_read_file (data, file->offset, len, buf);
+  return pupa_ext2_read_file (data, file->read_hook, file->offset, len, buf);
 }
 
 
@@ -654,7 +665,7 @@ pupa_ext2_dir (pupa_device_t device, const char *path,
     {
       struct ext2_dirent dirent;
        
-      pupa_ext2_read_file (data, fpos, sizeof (struct ext2_dirent),
+      pupa_ext2_read_file (data, 0, fpos, sizeof (struct ext2_dirent),
                           (char *) &dirent);
       if (pupa_errno)
        goto fail;
@@ -663,7 +674,7 @@ pupa_ext2_dir (pupa_device_t device, const char *path,
        {
          char filename[dirent.namelen + 1];
 
-         pupa_ext2_read_file (data, fpos + sizeof (struct ext2_dirent),
+         pupa_ext2_read_file (data, 0, fpos + sizeof (struct ext2_dirent),
                               dirent.namelen, filename);
          if (pupa_errno)
            goto fail;
index 942b09df50cbda98e5cd99be5330ab190cd61493..3914e008431f61481751a9ec96cd155047278e2e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
- *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
+ *  Copyright (C) 1999,2000,2001,2002,2004  Free Software Foundation, Inc.
  *  Copyright (C) 2003  Yoshinori K. Okuji <okuji@enbug.org>
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -24,7 +24,7 @@
 #define PUPA_LINUX_MAGIC_SIGNATURE     0x53726448      /* "HdrS" */
 #define PUPA_LINUX_DEFAULT_SETUP_SECTS 4
 #define PUPA_LINUX_FLAG_CAN_USE_HEAP   0x80
-#define PUPA_LINUX_INITRD_MAX_ADDRESS  0x38000000
+#define PUPA_LINUX_INITRD_MAX_ADDRESS  0x37FFFFFF
 #define PUPA_LINUX_MAX_SETUP_SECTS     64
 #define PUPA_LINUX_BOOT_LOADER_TYPE    0x72
 #define PUPA_LINUX_HEAP_END_OFFSET     (0x9000 - 0x200)
@@ -67,7 +67,8 @@ struct linux_kernel_header
   pupa_uint32_t header;                        /* Magic signature "HdrS" */
   pupa_uint16_t version;               /* Boot protocol version supported */
   pupa_uint32_t realmode_swtch;                /* Boot loader hook */
-  pupa_uint32_t start_sys;             /* Points to kernel version string */
+  pupa_uint16_t start_sys;             /* The load-low segment (obsolete) */
+  pupa_uint16_t kernel_version;                /* Points to kernel version string */
   pupa_uint8_t type_of_loader;         /* Boot loader identifier */
   pupa_uint8_t loadflags;              /* Boot protocol option flags */
   pupa_uint16_t setup_move_size;       /* Move to high memory size */
@@ -78,6 +79,7 @@ struct linux_kernel_header
   pupa_uint16_t heap_end_ptr;          /* Free memory after setup end */
   pupa_uint16_t pad1;                  /* Unused */
   char *cmd_line_ptr;                  /* Points to the kernel command line */
+  pupa_uint32_t initrd_addr_max;        /* Highest address for initrd */
 } __attribute__ ((packed));
 
 #endif /* ! ASM_FILE */
index b8fb77334c6106ba188e4f52a0394c5a51a1a499..6cd022723a099ba02dd6126ff4e13a50f0a931a2 100644 (file)
@@ -1,7 +1,7 @@
 /* linux.c - boot Linux zImage or bzImage */
 /*
  *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
- *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
+ *  Copyright (C) 1999,2000,2001,2002,2004  Free Software Foundation, Inc.
  *  Copyright (C) 2003  Yoshinori K. Okuji <okuji@enbug.org>
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -66,6 +66,7 @@ pupa_rescue_cmd_linux (int argc, char *argv[])
   struct linux_kernel_header lh;
   pupa_uint8_t setup_sects;
   pupa_size_t real_size, prot_size;
+  pupa_ssize_t len;
   int i;
   char *dest;
 
@@ -233,8 +234,13 @@ pupa_rescue_cmd_linux (int argc, char *argv[])
 
   /* Put the real mode code at the temporary address.  */
   pupa_memmove (pupa_linux_tmp_addr, &lh, sizeof (lh));
-  pupa_file_read (file, pupa_linux_tmp_addr + sizeof (lh),
-                 real_size + PUPA_DISK_SECTOR_SIZE - sizeof (lh));
+
+  len = real_size + PUPA_DISK_SECTOR_SIZE - sizeof (lh);
+  if (pupa_file_read (file, pupa_linux_tmp_addr + sizeof (lh), len) != len)
+    {
+      pupa_error (PUPA_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
 
   if (lh.header != pupa_cpu_to_le32 (PUPA_LINUX_MAGIC_SIGNATURE)
       || pupa_le_to_cpu16 (lh.version) < 0x0200)
@@ -261,8 +267,10 @@ pupa_rescue_cmd_linux (int argc, char *argv[])
 
   *dest = '\0';
 
-  pupa_file_read (file, (char *) PUPA_LINUX_BZIMAGE_ADDR, prot_size);
-  
+  len = prot_size;
+  if (pupa_file_read (file, (char *) PUPA_LINUX_BZIMAGE_ADDR, len) != len)
+    pupa_error (PUPA_ERR_FILE_READ_ERROR, "Couldn't read file");
   if (pupa_errno == PUPA_ERR_NONE)
     {
       pupa_linux_prot_size = prot_size;
@@ -285,9 +293,82 @@ pupa_rescue_cmd_linux (int argc, char *argv[])
 void
 pupa_rescue_cmd_initrd (int argc, char *argv[])
 {
-  pupa_error (PUPA_ERR_NOT_IMPLEMENTED_YET, "not implemented yet");
+  pupa_file_t file = 0;
+  pupa_ssize_t size;
+  pupa_addr_t addr_max, addr_min, addr;
+  struct linux_kernel_header *lh;
+
+  if (argc == 0)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "No module specified");
+      goto fail;
+    }
+  
+  if (!loaded)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "You need to load the kernel first.");
+      goto fail;
+    }
+
+  lh = (struct linux_kernel_header *) pupa_linux_tmp_addr;
+
+  if (!(lh->header == pupa_cpu_to_le32 (PUPA_LINUX_MAGIC_SIGNATURE)
+       && pupa_le_to_cpu16 (lh->version) >= 0x0200))
+    {
+      pupa_error (PUPA_ERR_BAD_OS, "The kernel is too old for initrd.");
+      goto fail;
+    }
+
+  /* Get the highest address available for the initrd.  */
+  if (pupa_le_to_cpu16 (lh->version) >= 0x0203)
+    addr_max = pupa_cpu_to_le32 (lh->initrd_addr_max);
+  else
+    addr_max = PUPA_LINUX_INITRD_MAX_ADDRESS;
+
+  if (!linux_mem_size && linux_mem_size < addr_max)
+    addr_max = linux_mem_size;
+
+  /* Linux 2.3.xx has a bug in the memory range check, so avoid
+     the last page.
+     Linux 2.2.xx has a bug in the memory range check, which is
+     worse than that of Linux 2.3.xx, so avoid the last 64kb.  */
+  addr_max -= 0x10000;
+
+  if (addr_max > pupa_os_area_addr + pupa_os_area_size)
+    addr_max = pupa_os_area_addr + pupa_os_area_size;
+
+  addr_min = (pupa_addr_t) pupa_linux_tmp_addr + PUPA_LINUX_CL_END_OFFSET;
+
+  file = pupa_file_open (argv[0]);
+  if (!file)
+    goto fail;
+
+  size = pupa_file_size (file);
+
+  /* Put the initrd as high as possible, 4Ki aligned.  */
+  addr = (addr_max - size) & ~0xFFF;
+
+  if (addr < addr_min)
+    {
+      pupa_error (PUPA_ERR_OUT_OF_RANGE, "The initrd is too big");
+      goto fail;
+    }
+
+  if (pupa_file_read (file, (void *)addr, size) != size)
+    {
+      pupa_error (PUPA_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  lh->ramdisk_image = addr;
+  lh->ramdisk_size = size;
+  
+ fail:
+  if (file)
+    pupa_file_close (file);
 }
 
+
 PUPA_MOD_INIT
 {
   pupa_rescue_register_command ("linux",