+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.
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.
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;
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;
}
int $0x10
jmp 3f
-
-1: movb $0x7, %bl
+
+1: movw $1, %bx
movb $0xe, %ah
int $0x10
popa
ret
-
+
/*
* int pupa_console_getkey (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 ();
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;
}
(pupa_cur_term->putchar) (c);
+
+ if (c == '\n')
+ pupa_putchar ('\r');
}
int
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
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)
/* 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;
}
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;
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__ */
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;
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 ())
{
{
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;
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;
}
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);
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)
{
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");
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);
}
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 ();
saved_cwd = xgetcwd ();
+ pupa_util_info ("changing current directory to %s", dir);
if (chdir (dir) < 0)
{
free (saved_cwd);
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. */
{
/* 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");
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''.");
}
}