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:
okuji 2003-01-02 23:46:21 +00:00
parent 1cc73a62da
commit 012d7999fe
8 changed files with 191 additions and 50 deletions

View file

@ -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
View file

@ -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.

View file

@ -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;
}

View 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)

View 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 ();

View 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

View 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);

View 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''.");
}
}