summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1999-02-27 23:39:00 +0000
committerRoland McGrath <roland@gnu.org>1999-02-27 23:39:00 +0000
commit300ee2caf49d6afa4ed6228ccf0a8d266080bc5e (patch)
tree363788beec2838eb453ef10361085c75b48fd778
parent0e4057bc0e1b9618be4c2fe761d685f4e98b8ddf (diff)
1999-02-27 Roland McGrath <roland@baalperazim.frob.com>
* def_pager_setup.c (add_paging_file): New arg CHECK_LINUX_SIGNATURE, pass down to create_paging_partition. * default_pager.c (create_paging_partition): New arg CHECK_LINUX_SIGNATURE, pass down new_partition. (new_partition): New arg CHECK_LINUX_SIGNATURE: if not < 0, check first page of swap for Linux 2.0 or 2.2 signature page and obey its bad-block map; if > 0, refuse the partition if no signature found. * bootstrap.c (main): Add new boot script functions `add-raw-paging-file', `add-linux-paging-file'. Make those and `add-paging-file' all call add_paging_file with new LINUX_SIGNATURE arg of -1, 1, and 0, respectively. * default_pager.c (create_paging_partition): If new_partition returns null, return and do nothing more.
-rw-r--r--serverboot/bootstrap.c36
-rw-r--r--serverboot/def_pager_setup.c5
-rw-r--r--serverboot/default_pager.c145
3 files changed, 172 insertions, 14 deletions
diff --git a/serverboot/bootstrap.c b/serverboot/bootstrap.c
index 3fa0f404..5c4a0393 100644
--- a/serverboot/bootstrap.c
+++ b/serverboot/bootstrap.c
@@ -146,12 +146,25 @@ main(argc, argv)
{
int doing_default_pager = 0;
int had_a_partition = 0;
- int script_paging_file (const struct cmd *cmd, int *val)
+ int script_paging_file (const struct cmd *cmd, int linux_signature)
{
if (add_paging_file (bootstrap_master_device_port, cmd->path))
printf ("(serverboot): %s: Cannot add paging file\n", cmd->path);
else
had_a_partition = 1;
+ return 0;
+ }
+ int script_add_paging_file (const struct cmd *cmd, int *val)
+ {
+ return script_paging_file (cmd, 0);
+ }
+ int script_add_raw_paging_file (const struct cmd *cmd, int *val)
+ {
+ return script_paging_file (cmd, -1);
+ }
+ int script_add_linux_paging_file (const struct cmd *cmd, int *val)
+ {
+ return script_paging_file (cmd, 1);
}
int script_default_pager (const struct cmd *cmd, int *val)
{
@@ -178,9 +191,9 @@ main(argc, argv)
*/
if (argv[1][0] != '-')
panic("bootstrap: no flags");
-
+
flag_string = argv[1];
-
+
/*
* Parse the arguments.
*/
@@ -208,13 +221,13 @@ main(argc, argv)
else if (argc == 3)
{
root_name = argv[2];
-
+
get_privileged_ports (&bootstrap_master_host_port,
&bootstrap_master_device_port);
}
-
-
-
+
+
+
printf_init(bootstrap_master_device_port);
#ifdef pleasenoXXX
@@ -275,7 +288,7 @@ main(argc, argv)
}
break;
}
-
+
/*
* If the server boot script name was changed,
* then use the new device name as the root device.
@@ -309,7 +322,12 @@ main(argc, argv)
|| boot_script_set_variable ("boot-args", VAL_STR,
(int) flag_string)
|| boot_script_define_function ("add-paging-file", VAL_NONE,
- &script_paging_file)
+ &script_add_paging_file)
+ || boot_script_define_function ("add-raw-paging-file", VAL_NONE,
+ &script_add_raw_paging_file)
+ || boot_script_define_function ("add-linux-paging-file",
+ VAL_NONE,
+ &script_add_linux_paging_file)
|| boot_script_define_function ("default-pager", VAL_NONE,
&script_default_pager)
)
diff --git a/serverboot/def_pager_setup.c b/serverboot/def_pager_setup.c
index fe6b33ab..cd72acea 100644
--- a/serverboot/def_pager_setup.c
+++ b/serverboot/def_pager_setup.c
@@ -35,9 +35,10 @@ extern void *kalloc();
extern void create_paging_partition();
kern_return_t
-add_paging_file(master_device_port, file_name)
+add_paging_file(master_device_port, file_name, linux_signature)
mach_port_t master_device_port;
char *file_name;
+ int linux_signature;
{
register struct file_direct *fdp;
register kern_return_t result;
@@ -68,7 +69,7 @@ add_paging_file(master_device_port, file_name)
/*
* Set up the default paging partition
*/
- create_paging_partition(file_name, fdp, isa_file);
+ create_paging_partition(file_name, fdp, isa_file, linux_signature);
return result;
}
diff --git a/serverboot/default_pager.c b/serverboot/default_pager.c
index 159cd576..dc1e7ff6 100644
--- a/serverboot/default_pager.c
+++ b/serverboot/default_pager.c
@@ -163,10 +163,14 @@ partition_init()
}
static partition_t
-new_partition (const char *name, struct file_direct *fdp)
+new_partition (const char *name, struct file_direct *fdp,
+ int check_linux_signature)
{
register partition_t part;
register vm_size_t size, bmsize;
+ vm_offset_t raddr;
+ mach_msg_type_number_t rsize;
+ int rc;
size = atop(fdp->fd_size * fdp->fd_bsize);
bmsize = howmany(size, NB_BM) * sizeof(bm_entry_t);
@@ -182,6 +186,138 @@ new_partition (const char *name, struct file_direct *fdp)
bzero((char *)part->bitmap, bmsize);
+ if (check_linux_signature < 0)
+ return part;
+
+#define LINUX_PAGE_SIZE 4096 /* size of pages in Linux swap partitions */
+ rc = page_read_file_direct(part->file,
+ 0, LINUX_PAGE_SIZE,
+ &raddr,
+ &rsize);
+ if (rc)
+ panic("(default pager): cannot read first page of %s! rc=%#x\n",
+ name, rc);
+ if (rsize != LINUX_PAGE_SIZE)
+ panic("(default pager): bad read on first page of %s! size=%u\n",
+ name, rsize);
+ if (!memcmp("SWAP-SPACE", (char *) raddr + LINUX_PAGE_SIZE-10, 10))
+ {
+ /* The partition's first page has a Linux swap signature.
+ This means the beginning of the page contains a bitmap
+ of good pages, and all others are bad. */
+ unsigned int i, j, bad;
+ printf("(default pager): Found Linux 2.0 swap signature in %s...",
+ name);
+ part->bitmap[0] |= 1; /* first page unusable */
+ part->free--;
+ bad = 0;
+ memset((char *) raddr + LINUX_PAGE_SIZE-10, 0, 10);
+ for (i = 0; i < LINUX_PAGE_SIZE / sizeof(bm_entry_t); ++i)
+ {
+ bm_entry_t bm = ((bm_entry_t *) raddr)[i];
+ if (bm == BM_MASK)
+ continue;
+ /* There are some zero bits in this word. */
+ for (j = 0; j < NB_BM; ++j)
+ if ((bm & (1 << j)) == 0)
+ {
+ ++bad;
+ part->bitmap[i] |= 1 << j;
+ }
+ }
+ part->free -= bad;
+ printf ("%dk swap-space (excludes %dk marked bad)\n",
+ part->free * (LINUX_PAGE_SIZE / 1024),
+ bad * (LINUX_PAGE_SIZE / 1024));
+ if (part->total_size > 8 * LINUX_PAGE_SIZE)
+ {
+ unsigned int waste = part->total_size - (8 * LINUX_PAGE_SIZE);
+ part->free -= waste;
+ part->total_size -= waste;
+ printf("\
+(default pager): NOTE: wasting last %dk of %s past Linux max swapfile size\n",
+ waste * (LINUX_PAGE_SIZE / 1024), name);
+ }
+ }
+ else if (!memcmp("SWAPSPACE2",
+ (char *) raddr + LINUX_PAGE_SIZE-10, 10))
+ {
+ struct
+ {
+ u_int8_t bootbits[1024];
+ u_int32_t version;
+ u_int32_t last_page;
+ u_int32_t nr_badpages;
+ u_int32_t padding[125];
+ u_int32_t badpages[1];
+ } *hdr = (void *) raddr;
+
+ printf("\
+(default pager): Found Linux 2.2 swap signature (v%u) in %s...",
+ name, hdr->version);
+
+ part->bitmap[0] |= 1; /* first page unusable */
+ part->free--;
+
+ switch (hdr->version)
+ {
+ default:
+ if (check_linux_signature)
+ {
+ printf ("version %u unknown! SKIPPING %s!\n",
+ hdr->version,
+ name);
+ return 0;
+ }
+ else
+ printf ("version %u unknown! IGNORING SIGNATURE PAGE!"
+ " %dk swap-space\n",
+ hdr->version,
+ part->free * (LINUX_PAGE_SIZE / 1024));
+ break;
+
+ case 1:
+ {
+ unsigned int waste, i;
+ if (hdr->last_page > part->total_size)
+ {
+ printf ("signature says %uk, partition has only %uk! ",
+ hdr->last_page * (LINUX_PAGE_SIZE / 1024),
+ part->total_size * (LINUX_PAGE_SIZE / 1024));
+ waste = 0;
+ }
+ else
+ {
+ waste = part->total_size - hdr->last_page;
+ part->total_size = hdr->last_page;
+ }
+ for (i = 0; i < hdr->nr_badpages; ++i)
+ {
+ const u_int32_t bad = hdr->badpages[i];
+ part->bitmap[bad / NB_BM] |= 1 << (i % NB_BM);
+ part->free--;
+ }
+ printf ("%uk swap-space",
+ part->free * (LINUX_PAGE_SIZE / 1024));
+ if (hdr->nr_badpages != 0)
+ printf (" (excludes %uk marked bad)",
+ hdr->nr_badpages * (LINUX_PAGE_SIZE / 1024));
+ if (waste != 0)
+ printf (" (excludes %uk pages at end of partition)",
+ waste * (LINUX_PAGE_SIZE / 1024));
+ printf ("\n");
+ }
+ }
+ }
+ else if (check_linux_signature)
+ {
+ part = 0;
+ printf ("(default pager): "
+ "Cannot find Linux swap signature page! SKIPPING %s!",
+ name);
+ }
+ vm_deallocate(mach_task_self(), raddr, rsize);
+
return part;
}
@@ -192,11 +328,14 @@ new_partition (const char *name, struct file_direct *fdp)
*/
void
create_paging_partition(const char *name,
- struct file_direct *fdp, int isa_file)
+ struct file_direct *fdp, int isa_file,
+ int linux_signature)
{
register partition_t part;
- part = new_partition (name, fdp);
+ part = new_partition (name, fdp, linux_signature);
+ if (!part)
+ return;
mutex_lock(&all_partitions.lock);
{