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.
This commit is contained in:
parent
1cc73a62da
commit
012d7999fe
8 changed files with 191 additions and 50 deletions
32
ChangeLog
32
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.
|
||||
|
|
3
NEWS
3
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.
|
||||
|
|
10
fs/fat.c
10
fs/fat.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -992,7 +992,7 @@ FUNCTION(pupa_console_putchar)
|
|||
|
||||
jmp 3f
|
||||
|
||||
1: movb $0x7, %bl
|
||||
1: movw $1, %bx
|
||||
movb $0xe, %ah
|
||||
int $0x10
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
if (have_devfs () && strcmp (dev + len - 5, "/disc") == 0)
|
||||
real_dev = xstrdup (dev);
|
||||
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
free (real_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ioctl (fd, HDIO_GETGEO, &hdg))
|
||||
{
|
||||
close (fd);
|
||||
free (real_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
|
||||
if (hdg.start == sector)
|
||||
{
|
||||
strcpy (dev, real_dev);
|
||||
free (real_dev);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
free (real_dev);
|
||||
return 0;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
@ -266,6 +313,7 @@ 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)
|
||||
{
|
||||
|
@ -273,6 +321,9 @@ open_device (const pupa_disk_t disk, unsigned long sector, int flags)
|
|||
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 ())
|
||||
{
|
||||
|
@ -654,7 +705,7 @@ 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;
|
||||
|
@ -721,16 +780,24 @@ 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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
#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);
|
||||
|
@ -289,6 +310,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 ();
|
||||
sleep (1);
|
||||
|
@ -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''.");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue