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> 2003-01-03 Yoshinori K. Okuji <okuji@enbug.org>
* include/i386/pc/util/biosdisk.h: New file. * 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 care when writing assembly code. See the comments at the beginning of
startup.S, for more details. 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: New in 0.6 - 2002-12-27, Yoshinori K. Okuji:
* The chainloader and the FAT filesystem are modularized. * 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)); data = (struct pupa_fat_data *) pupa_malloc (sizeof (*data));
if (! data) if (! data)
goto fail; goto fail;
/* Read the BPB. */ /* Read the BPB. */
if (pupa_disk_read (disk, 0, 0, sizeof (bpb), (char *) &bpb)) if (pupa_disk_read (disk, 0, 0, sizeof (bpb), (char *) &bpb))
goto fail; goto fail;
@ -437,19 +437,25 @@ pupa_fat_read_data (pupa_disk_t disk, struct pupa_fat_data *data,
break; break;
case 12: case 12:
if (data->cur_cluster & 1) if (data->cur_cluster & 1)
next_cluster >>= 12; next_cluster >>= 4;
next_cluster &= 0x0FFF; next_cluster &= 0x0FFF;
break; 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. */ /* Check the end. */
if (next_cluster >= data->cluster_eof_mark) if (next_cluster >= data->cluster_eof_mark)
return ret; return ret;
if (next_cluster < 2 || next_cluster >= data->num_clusters) 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; return -1;
} }

View file

@ -991,8 +991,8 @@ FUNCTION(pupa_console_putchar)
int $0x10 int $0x10
jmp 3f jmp 3f
1: movb $0x7, %bl 1: movw $1, %bx
movb $0xe, %ah movb $0xe, %ah
int $0x10 int $0x10
@ -1001,7 +1001,7 @@ FUNCTION(pupa_console_putchar)
popa popa
ret ret
/* /*
* int pupa_console_getkey (void) * int pupa_console_getkey (void)

View file

@ -67,9 +67,8 @@ pupa_main (void)
/* Hello. */ /* Hello. */
pupa_setcolorstate (PUPA_TERM_COLOR_HIGHLIGHT); 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_setcolorstate (PUPA_TERM_COLOR_STANDARD);
pupa_printf ("\n\n");
pupa_register_exported_symbols (); pupa_register_exported_symbols ();
pupa_load_modules (); pupa_load_modules ();

View file

@ -73,9 +73,7 @@ pupa_term_get_current (void)
void void
pupa_putchar (int c) pupa_putchar (int c)
{ {
if (c == '\n') if (c == '\t' && pupa_cur_term->getxy)
pupa_putchar ('\r');
else if (c == '\t' && pupa_cur_term->getxy)
{ {
int n; int n;
@ -87,6 +85,9 @@ pupa_putchar (int c)
} }
(pupa_cur_term->putchar) (c); (pupa_cur_term->putchar) (c);
if (c == '\n')
pupa_putchar ('\r');
} }
int int

View file

@ -66,6 +66,9 @@ struct hd_geometry
unsigned long start; unsigned long start;
}; };
# endif /* ! HDIO_GETGEO */ # endif /* ! HDIO_GETGEO */
# ifndef BLKGETSIZE
# define BLKGETSIZE _IO(0x12,96) /* return device size */
# endif /* ! BLKGETSIZE */
# ifndef MAJOR # ifndef MAJOR
# ifndef MINORBITS # ifndef MINORBITS
# define MINORBITS 8 # define MINORBITS 8
@ -165,7 +168,34 @@ pupa_util_biosdisk_open (const char *name, pupa_disk_t disk)
disk->id = drive; disk->id = drive;
/* Get the size. */ /* 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]); return pupa_error (PUPA_ERR_BAD_DEVICE, "cannot stat `%s'", map[drive]);
if (st.st_blocks) if (st.st_blocks)
@ -174,6 +204,8 @@ pupa_util_biosdisk_open (const char *name, pupa_disk_t disk)
/* Hmm... Use st_size instead. */ /* Hmm... Use st_size instead. */
disk->total_sectors = st.st_size >> PUPA_DISK_SECTOR_BITS; 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; return PUPA_ERR_NONE;
} }
@ -185,22 +217,25 @@ linux_find_partition (char *dev, unsigned long sector)
const char *format; const char *format;
char *p; char *p;
int i; 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"; format = "part%d";
} }
else if ((strncmp (dev + 5, "hd", 2) == 0 else if ((strncmp (real_dev + 5, "hd", 2) == 0
|| strncmp (dev + 5, "sd", 2) == 0) || strncmp (real_dev + 5, "sd", 2) == 0)
&& dev[7] >= 'a' && dev[7] <= 'z') && real_dev[7] >= 'a' && real_dev[7] <= 'z')
{ {
p = dev + 8; p = real_dev + 8;
format = "%d"; 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) if (! p)
return 0; return 0;
@ -211,30 +246,42 @@ linux_find_partition (char *dev, unsigned long sector)
format = "p%d"; format = "p%d";
} }
else else
return 0; {
free (real_dev);
return 0;
}
for (i = 0; i < 10000; i++) for (i = 1; i < 10000; i++)
{ {
int fd; int fd;
struct hd_geometry hdg; struct hd_geometry hdg;
sprintf (p, format, i); sprintf (p, format, i);
fd = open (dev, O_RDONLY); fd = open (real_dev, O_RDONLY);
if (! fd) if (! fd)
return 0; {
free (real_dev);
return 0;
}
if (ioctl (fd, HDIO_GETGEO, &hdg)) if (ioctl (fd, HDIO_GETGEO, &hdg))
{ {
close (fd); close (fd);
free (real_dev);
return 0; return 0;
} }
close (fd); close (fd);
if (hdg.start == sector) if (hdg.start == sector)
return 1; {
strcpy (dev, real_dev);
free (real_dev);
return 1;
}
} }
free (real_dev);
return 0; return 0;
} }
#endif /* __linux__ */ #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); is_partition = linux_find_partition (dev, disk->partition->start);
/* Open the partition. */ /* Open the partition. */
pupa_util_info ("opening the device `%s'", dev);
fd = open (dev, flags); fd = open (dev, flags);
if (fd < 0) if (fd < 0)
{ {
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot open `%s'", dev); pupa_error (PUPA_ERR_BAD_DEVICE, "cannot open `%s'", dev);
return -1; return -1;
} }
/* Make the buffer cache consistent with the physical disk. */
ioctl (fd, BLKFLSBUF, 0);
if (is_partition) if (is_partition)
sector -= disk->partition->start; sector -= disk->partition->start;
@ -560,9 +611,9 @@ get_os_disk (const char *os_dev)
if (! realpath (os_dev, path)) if (! realpath (os_dev, path))
return 0; return 0;
if (strncmp ("/dev/", path, 4) == 0) if (strncmp ("/dev/", path, 5) == 0)
{ {
p = path + 4; p = path + 5;
if (have_devfs ()) if (have_devfs ())
{ {
@ -653,8 +704,8 @@ pupa_util_biosdisk_get_pupa_dev (const char *os_dev)
{ {
struct stat st; struct stat st;
int drive; 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); pupa_error (PUPA_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
return 0; return 0;
@ -687,6 +738,14 @@ pupa_util_biosdisk_get_pupa_dev (const char *os_dev)
int find_partition (const pupa_partition_t partition) 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) if (hdg.start == partition->start)
{ {
dos_part = partition->dos_part; dos_part = partition->dos_part;
@ -720,17 +779,25 @@ pupa_util_biosdisk_get_pupa_dev (const char *os_dev)
} }
close (fd); close (fd);
pupa_util_info ("%s starts from %lu", os_dev, hdg.start);
if (hdg.start == 0) if (hdg.start == 0)
return name; return name;
pupa_util_info ("opening the device %s", name);
disk = pupa_disk_open (name); disk = pupa_disk_open (name);
free (name); free (name);
if (! disk) if (! disk)
return 0; 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) if (dos_part < 0)
{ {
pupa_disk_close (disk); 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_uint16_t last_length = PUPA_DISK_SECTOR_SIZE;
pupa_file_t file; pupa_file_t file;
FILE *fp; FILE *fp;
unsigned long first_start = ~0UL;
auto void save_first_sector (unsigned long sector, unsigned offset, auto void save_first_sector (unsigned long sector, unsigned offset,
unsigned length); unsigned length);
auto void save_blocklists (unsigned long sector, unsigned offset, auto void save_blocklists (unsigned long sector, unsigned offset,
unsigned length); 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, void save_first_sector (unsigned long sector, unsigned offset,
unsigned length) unsigned length)
{ {
@ -195,23 +208,10 @@ setup (const char *prefix, const char *dir,
try to embed the core image into after the MBR. */ try to embed the core image into after the MBR. */
if (dest_dev->disk->has_partitions && ! dest_dev->disk->partition) 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); pupa_partition_iterate (dest_dev->disk, find_first_partition_start);
/* If there is enough space... */ /* 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 ("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", pupa_util_info ("succeeded in opening the core image but cannot read %d bytes",
(int) core_size); (int) core_size);
else if (memcmp (core_img, tmp_img, core_size) != 0) 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 else
{ {
pupa_file_close (file); pupa_file_close (file);
@ -288,6 +309,9 @@ setup (const char *prefix, const char *dir,
} }
else else
pupa_util_info ("couldn't open the core image"); 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; pupa_errno = PUPA_ERR_NONE;
sync (); sync ();
@ -530,6 +554,7 @@ find_root_device (const char *dir, dev_t dev)
saved_cwd = xgetcwd (); saved_cwd = xgetcwd ();
pupa_util_info ("changing current directory to %s", dir);
if (chdir (dir) < 0) if (chdir (dir) < 0)
{ {
free (saved_cwd); 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) if (strcmp (ent->d_name, ".") == 0 || strcmp (ent->d_name, "..") == 0)
continue; continue;
if (stat (ent->d_name, &st) < 0) if (lstat (ent->d_name, &st) < 0)
/* Ignore any error. */ /* Ignore any error. */
continue; continue;
if (S_ISLNK (st.st_mode))
/* Don't follow symbolic links. */
continue;
if (S_ISDIR (st.st_mode)) if (S_ISDIR (st.st_mode))
{ {
/* Find it recursively. */ /* Find it recursively. */
@ -570,11 +599,13 @@ find_root_device (const char *dir, dev_t dev)
{ {
/* Found! */ /* Found! */
char *res; char *res;
char *cwd;
res = xmalloc (strlen (saved_cwd) + strlen (dir) cwd = xgetcwd ();
+ strlen (ent->d_name) + 3); res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 2);
sprintf (res, "%s/%s/%s", saved_cwd, dir, ent->d_name); sprintf (res, "%s/%s", cwd, ent->d_name);
strip_extra_slashes (res); strip_extra_slashes (res);
free (cwd);
if (chdir (saved_cwd) < 0) if (chdir (saved_cwd) < 0)
pupa_util_error ("Cannot restore the original directory"); 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); root_dev = guess_root_device (dir ? : DEFAULT_DIRECTORY);
if (! root_dev) 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''."); pupa_util_error ("Cannot guess the root device. Specify the option ``--root-device''.");
} }
} }