[parisc-linux] Allow palo partition to be mounted as ext2
James Bottomley
James.Bottomley@steeleye.com
07 Nov 2003 19:13:55 -0600
It can be a bit of a pain having both a palo partition and a /boot
partition on the root disc (and both < 2GB), so this patch allows the
palo partition to be mounted as an ordinary ext2/ext3 filesystem
(ideally as /boot).
It does this by creating an ext2/3 filesystem in the palo partition but
leaving a hole for the iplboot program (by telling the filesystem the
blocks are bad). The kernels can be booted from this filesystem by
specifying 0/ as the partition as usual.
Attached is a preliminary patch for you to see what you think.
Ultimately, it should mean we can get palo to operate much more like
grub (using a palo.conf file within the palo partition itself for
instance).
The diffs are against the palo cvs tree.
James
Index: ipl/ipl.c
===================================================================
RCS file: /var/cvs/palo/ipl/ipl.c,v
retrieving revision 1.32
diff -u -r1.32 ipl.c
--- ipl/ipl.c 13 Jan 2003 19:41:24 -0000 1.32
+++ ipl/ipl.c 8 Nov 2003 01:05:54 -0000
@@ -252,7 +252,7 @@
int blocked_bootdev;
int bootdev;
int wide;
- int kern_part, rd_part, i;
+ int kern_part, rd_part, i, ext2 = 0, f0;
char kern_name[128], rd_name[128];
char kern_fullname[128];
@@ -294,6 +294,11 @@
printf("\n%s contains:\n",
partitioned ? "PALO(F0) partition" : "Boot image");
+ if(partitioned && f.version >= 4 && (f.flags & PFLAG_EXT2)) {
+ printf("PALO is formatted EXT2/3\n");
+ ext2 = 1;
+ }
+
if (f.version < 3 && f.kern32_sz > 0)
{
printf(" 0/vmlinux %d bytes @ 0x%x\n", f.kern32_sz, f.kern32_offset);
@@ -392,16 +397,23 @@
{
if (partition[i].id == 0xf0)
{
- if (kern_part == i + 1)
+ f0 = i + 1;
+ if (kern_part == f0)
kern_part = 0;
- if (rd_part == i + 1)
+ if (rd_part == f0)
rd_part = 0;
break;
}
}
+ if (ext2 && kern_part == 0) {
+ kern_part = f0;
+ if(rd_part == 0)
+ rd_part = f0;
+ }
+
if (kern_part > 0 && !partitioned)
{
printf("ERROR: Requesting kernel from partition %d "
@@ -507,7 +519,7 @@
struct diskpartition *pp;
if (kern_part >= MAXPARTS ||
- (partition[kern_part - 1].id != 0x83 && partition[kern_part - 1].id != 0xfd) )
+ (partition[kern_part - 1].id != 0x83 && partition[kern_part - 1].id != 0xfd && partition[kern_part - 1].id != 0xf0) )
{
printf("ERROR: Partition %d must be ext2\n", kern_part);
while(1);
Index: lib/common.h
===================================================================
RCS file: /var/cvs/palo/lib/common.h,v
retrieving revision 1.24
diff -u -r1.24 common.h
--- lib/common.h 14 Jan 2003 20:32:44 -0000 1.24
+++ lib/common.h 8 Nov 2003 01:05:55 -0000
@@ -11,7 +11,7 @@
#include <asm/byteorder.h>
#include <linux/genhd.h>
-#define PALOVERSION "1.2"
+#define PALOVERSION "1.3"
/* size of I/O block used in HP firmware */
#define FW_BLOCKSIZE 2048
@@ -28,9 +28,10 @@
* kern_sz = 0 or rd_sz = 0 means no kern or ramdisk respectively.
*/
#define PALOMAGIC "PALO"
-#define PALOHDRVERSION 3
+#define PALOHDRVERSION 4
#define PFLAG_INSTALL 0x1
+#define PFLAG_EXT2 0x2
struct firstblock
{
Index: palo/error.c
===================================================================
RCS file: /var/cvs/palo/palo/error.c,v
retrieving revision 1.6
diff -u -r1.6 error.c
--- palo/error.c 14 Jun 2001 19:39:58 -0000 1.6
+++ palo/error.c 8 Nov 2003 01:05:55 -0000
@@ -83,6 +83,13 @@
/* 17 */
"Too many of the same type of kernel. %s is either the second\n"
"32-bit kernel or the second 64-bit one.\n",
+
+ /* 18 */
+ "For formatted palo partitions, you cannot specify a kernel\n"
+ "or a ramdisk.\n",
+
+ /* 19 */
+ "mke2fs failed."
};
#define NMESSAGES (sizeof errormessages / sizeof errormessages[0])
Index: palo/palo.c
===================================================================
RCS file: /var/cvs/palo/palo/palo.c,v
retrieving revision 1.16
diff -u -r1.16 palo.c
--- palo/palo.c 6 Aug 2002 15:22:14 -0000 1.16
+++ palo/palo.c 8 Nov 2003 01:05:56 -0000
@@ -17,6 +17,8 @@
#include <string.h>
#include <ctype.h>
#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#if LONG_OPTIONS
# define _GNU_SOURCE
# include <getopt.h>
@@ -30,6 +32,7 @@
static const char Id[] = "$Id: palo.c,v 1.12.4.1 2001/06/13 03:13:17 bame Exp $";
static int Install = 0;
+int verbose = 0;
/* compute the sum of words in an 4-byte aligned region */
int
@@ -39,7 +42,7 @@
int *x = (int *)p;
int i;
- if (0) printf("checksum(%p, %u) = ", p, len);
+ if (verbose) printf("checksum(%p, %u) = ", p, len);
len /= 4;
for (i = 0; i < len; i++)
@@ -47,7 +50,7 @@
xsum += B32(x[i]);
}
- if (0) printf("0x%08x\n", xsum);
+ if (verbose) printf("0x%08x\n", xsum);
return (xsum);
}
@@ -74,7 +77,7 @@
int xsum;
unsigned int *ipl;
- if (0) printf("check_bootloader %d\n", line);
+ if (verbose) printf("check_bootloader %d\n", line);
STRUCTREAD(media, f, 0);
@@ -173,9 +176,11 @@
error(12);
/* make sure max size boot loader would fit */
- if (where + MAXBLSIZE >= f0end)
+ if (where + MAXBLSIZE > f0end) {
+ printf("where %d, where+MAX=%d f0end=%d\n",
+ where, where + MAXBLSIZE, f0end);
error(9);
-
+ }
/* load the boot loader into RAM */
rblsize = fsize(bootloader);
assert((rblsize % FW_BLOCKSIZE) == 0);
@@ -425,6 +430,98 @@
#define KSIZE (2 * 1024 * 1024)
+/* Blocksize for the ext2/3 fs in the palo partition */
+#define EXT2_BLOCKSIZE 1024
+
+/* size in ext2 blocks of hole for bootloader */
+#define EXT2_HOLE ((MAXBLSIZE + 1) / EXT2_BLOCKSIZE)
+
+/* offset in bytes before start of hole, ext2 doesn't allow holes at
+ * to cover the first four blocks of the filesystem */
+#define EXT2_OFFSET (4*EXT2_BLOCKSIZE)
+
+void
+do_formatted(int init, int media, const char *medianame, int partition,
+ int f0start, int f0length, int bootloaderfd, int do_format,
+ const char *commandline)
+{
+ char partitionname[256];
+ struct firstblock f;
+ int partitionfd;
+
+ /* FIXME: assuming we can simply add the partition to the end
+ * of the whole disc device isn't always true */
+ snprintf(partitionname, sizeof(partitionname), "%s%d", medianame,
+ partition);
+
+ if ((partitionfd = open(partitionname, O_RDWR)) < 0) {
+ perror(partitionname);
+ exit(1);
+ }
+ close(partitionfd);
+
+ if (init) {
+ /* make the bootloader align at 256k */
+ unsigned int holestart = (f0start + 0x3ffff + EXT2_OFFSET) & ~0x3ffff;
+ unsigned int partition_offset = holestart - f0start;
+ char badblockfilename[256];
+ int fd, i;
+ char cmd[512];
+
+ if (verbose)
+ printf("f0 partition starts %d, hole %d-%d, end %d\n",
+ f0start, holestart, holestart + EXT2_HOLE*EXT2_BLOCKSIZE,
+ f0start + f0length);
+
+ if(partition_offset + EXT2_HOLE > f0length)
+ error(14, "bootloader");
+
+ sprintf(badblockfilename, "/tmp/paloblk-%d", getpid());
+ if ((fd = open(badblockfilename, O_RDWR | O_CREAT | O_TRUNC)) < 0) {
+ perror(badblockfilename);
+ exit(1);
+ }
+
+ for (i = (holestart - f0start)/EXT2_BLOCKSIZE;
+ i < (holestart - f0start)/EXT2_BLOCKSIZE + EXT2_HOLE; i++) {
+ char buf[128];
+ sprintf(buf, "%d\n", i);
+ write(fd, buf, strlen(buf));
+ }
+
+ sprintf(cmd, "mke2fs %s -b %d -l %s %s", do_format == 3 ? "-j" : "",
+ EXT2_BLOCKSIZE, badblockfilename, partitionname);
+
+ if (verbose)
+ printf("Executing: %s\n", cmd);
+ else
+ strcat(cmd, " > /dev/null 2>&1");
+
+ i = system(cmd);
+ unlink(badblockfilename);
+
+ if(WEXITSTATUS(i) != 0)
+ error(20);
+
+
+
+ STRUCTREAD(media, f, 0);
+ fb_init(&f);
+ f.flags |= PFLAG_EXT2;
+
+ if(commandline)
+ strcpy(f.cmdline, commandline);
+
+ write_bootloader(media, bootloaderfd, holestart,
+ holestart + EXT2_HOLE*EXT2_BLOCKSIZE, &f);
+
+ STRUCTWRITE(media, f, 0);
+
+ }
+
+
+}
+
void
do_randomaccess(int init, int media, int kernel32, int kernel64,
const char *commandline, int bootloader, int ramdisk,
@@ -433,7 +530,7 @@
struct firstblock f;
int bstart = 0;
- if (0) printf("do_ra(%d, %d, %d, %d, '%s', %d, %d, %u, %u)\n",
+ if (verbose) printf("do_ra(%d, %d, %d, %d, '%s', %d, %d, %u, %u)\n",
init, media, kernel32, kernel64, commandline, bootloader, ramdisk, f0start,
f0length);
@@ -552,9 +649,11 @@
{"bootloader", 1, 0, 'b'},
{"ramdisk", 1, 0, 'r'},
{"init-partitioned", 1, 0, 'I'},
+ {"format-as", 1, 0, 'e'},
{"update-partitioned", 1, 0, 'U'},
{"init-tape", 1, 0, 's'},
{"init-cdrom", 1, 0, 'C'},
+ {"verbose", 0, 0, 'v'},
{"help", 0, 0, '?'},
{0, 0, 0, 0}
};
@@ -583,10 +682,10 @@
char *bootloaderfile = "/usr/share/palo/iplboot";
int init = 0;
extern char *bld_info;
- const char gargs[] = "f:C:s:b:k:c:r:I:?";
+ const char gargs[] = "f:C:s:b:k:c:r:I:e:v?";
char *config_file = "/etc/palo.conf";
char *newargv[MAXARGS];
- int newargc;
+ int newargc, format_as = 0;
FILE *fconfig;
assert(sizeof (struct firstblock) == 2048);
@@ -720,6 +819,17 @@
if (strlen(commandline) > 127)
error(3);
break;
+ case 'e':
+ if(strcmp(optarg, "2") == 0)
+ format_as = 2;
+ else if(strcmp(optarg, "3") == 0)
+ format_as = 3;
+ else
+ error(0, argv[0]);
+ break;
+ case 'v':
+ verbose = 1;
+ break;
default:
error(0, argv[0]);
break;
@@ -787,13 +897,28 @@
}
if (f0 == MAXPARTS)
error(11);
- print_ptab_pretty(ptab, MAXPARTS);
+ if(verbose) {
+ print_ptab_pretty(ptab, MAXPARTS);
- if (0) printf("F0 partition start sector %d length %d\n",
+ printf("F0 partition start sector %d length %d\n",
ptab[f0].start, ptab[f0].length);
+ }
- do_randomaccess(init, media, kernel32, kernel64, commandline, bootloader,
- ramdisk, ptab[f0].start * 512, ptab[f0].length * 512);
+ if (format_as) {
+ /* if we're going to be a formatted partition, we can't
+ * load anything into it, so check we haven't been asked
+ * to */
+ if(kernel32 != -1 || kernel64 != -1
+ || ramdisk != -1)
+ error(18);
+ printf("OK we're doing a format as ext%d\n", format_as);
+ do_formatted(init, media, medianame, f0 + 1,
+ ptab[f0].start * 512, ptab[f0].length * 512,
+ bootloader, format_as, commandline);
+ } else
+ do_randomaccess(init, media, kernel32, kernel64, commandline,
+ bootloader, ramdisk, ptab[f0].start * 512,
+ ptab[f0].length * 512);
}
break;
case CDROM:
Index: palo/usage.txt
===================================================================
RCS file: /var/cvs/palo/palo/usage.txt,v
retrieving revision 1.3
diff -u -r1.3 usage.txt
--- palo/usage.txt 6 Aug 2002 15:35:22 -0000 1.3
+++ palo/usage.txt 8 Nov 2003 01:05:56 -0000
@@ -46,6 +46,15 @@
When -f is not specified, palo tries /etc/palo.conf. Use
--configfile=/dev/null to avoid configuration files or
warnings when /etc/palo.conf is missing.
+ -v, --verbose
+ Provide more verbose information when running palo
+ -e, --format-as=type
+ This is only for partitioned media: Format the palo
+ partition as an ext2 (type == 2) or ext3 (type == 3)
+ partition. With this option, you cannot specify
+ any parameters, kernels or ramdisks to be loaded into
+ the palo partition
+
'palo' with no arguments whatsoever is equivalent to 'palo -f /etc/palo.conf'.