83702273a3
always to the first 16 sectors of the disk. The firmware reads the boot code from a partition, defaulting to 'a' if none is specified, which only corresponds to the first 16 sectors of the disk if 'a' is first. Solaris often makes the swap partition first, instead of the root partition, and users expect to be able to do the same with freebsd as well. This also allows one to temporarily boot from another partition if the boot block on the root partition gets scrambled somehow.
108 lines
2.7 KiB
C
108 lines
2.7 KiB
C
/*
|
|
* ----------------------------------------------------------------------------
|
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
|
* <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
|
|
* can do whatever you want with this stuff. If we meet some day, and you think
|
|
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <err.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/sun_disklabel.h>
|
|
#include <paths.h>
|
|
#include <errno.h>
|
|
#include "libdisk.h"
|
|
|
|
int
|
|
Write_Disk(const struct disk *d1)
|
|
{
|
|
struct sun_disklabel *sl;
|
|
struct chunk *c, *c1, *c2;
|
|
int i;
|
|
char *p;
|
|
u_long secpercyl;
|
|
u_short *sp1, *sp2, cksum;
|
|
char device[64];
|
|
int fd;
|
|
|
|
strcpy(device,_PATH_DEV);
|
|
strcat(device,d1->name);
|
|
|
|
fd = open(device,O_RDWR);
|
|
if (fd < 0) {
|
|
warn("open(%s) failed", device);
|
|
return (1);
|
|
}
|
|
|
|
sl = calloc(sizeof *sl, 1);
|
|
c = d1->chunks;
|
|
c2 = c->part;
|
|
secpercyl = d1->bios_sect * d1->bios_hd;
|
|
sl->sl_pcylinders = c->size / secpercyl;
|
|
sl->sl_ncylinders = c2->size / secpercyl;
|
|
sl->sl_acylinders = sl->sl_pcylinders - sl->sl_ncylinders;
|
|
sl->sl_magic = SUN_DKMAGIC;
|
|
sl->sl_nsectors = d1->bios_sect;
|
|
sl->sl_ntracks = d1->bios_hd;
|
|
if (c->size > 4999 * 1024 * 2) {
|
|
sprintf(sl->sl_text, "FreeBSD%luG cyl %u alt %u hd %u sec %u",
|
|
(c->size + 1024 * 1024) / (2 * 1024 * 1024),
|
|
sl->sl_ncylinders, sl->sl_acylinders,
|
|
sl->sl_ntracks, sl->sl_nsectors);
|
|
} else {
|
|
sprintf(sl->sl_text, "FreeBSD%luM cyl %u alt %u hd %u sec %u",
|
|
(c->size + 1024) / (2 * 1024),
|
|
sl->sl_ncylinders, sl->sl_acylinders,
|
|
sl->sl_ntracks, sl->sl_nsectors);
|
|
}
|
|
sl->sl_interleave = 1;
|
|
sl->sl_sparespercyl = 0;
|
|
sl->sl_rpm = 3600;
|
|
|
|
for (c1 = c2->part; c1 != NULL; c1 = c1->next) {
|
|
p = c1->name;
|
|
p += strlen(p);
|
|
p--;
|
|
if (*p < 'a' || *p > 'h')
|
|
continue;
|
|
i = *p - 'a';
|
|
sl->sl_part[i].sdkp_cyloffset = c1->offset / secpercyl;
|
|
sl->sl_part[i].sdkp_nsectors = c1->size;
|
|
for (i = 1; i < 16; i++) {
|
|
write_block(fd, c1->offset + i, d1->boot1 + (i * 512),
|
|
512);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We need to fill in the "RAW" partition as well. Emperical data
|
|
* seems to indicate that this covers the "obviously" visible part
|
|
* of the disk, ie: sl->sl_ncylinders.
|
|
*/
|
|
sl->sl_part[2].sdkp_cyloffset = 0;
|
|
sl->sl_part[2].sdkp_nsectors = sl->sl_ncylinders * secpercyl;
|
|
|
|
sp1 = (u_short *)sl;
|
|
sp2 = (u_short *)(sl + 1);
|
|
sl->sl_cksum = cksum = 0;
|
|
while (sp1 < sp2)
|
|
cksum ^= *sp1++;
|
|
sl->sl_cksum = cksum;
|
|
|
|
write_block(fd, 0, sl, sizeof *sl);
|
|
|
|
close(fd);
|
|
return 0;
|
|
}
|