diff options
author | Roland McGrath <roland@gnu.org> | 1999-02-27 23:39:00 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1999-02-27 23:39:00 +0000 |
commit | 300ee2caf49d6afa4ed6228ccf0a8d266080bc5e (patch) | |
tree | 363788beec2838eb453ef10361085c75b48fd778 | |
parent | 0e4057bc0e1b9618be4c2fe761d685f4e98b8ddf (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.c | 36 | ||||
-rw-r--r-- | serverboot/def_pager_setup.c | 5 | ||||
-rw-r--r-- | serverboot/default_pager.c | 145 |
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); { |