2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
9 * $FreeBSD: src/lib/libdisk/write_disk.c,v 1.28.2.10 2001/05/13 21:01:38 jkh Exp $
10 * $DragonFly: src/lib/libdisk/Attic/write_disk.c,v 1.4 2005/03/13 15:10:03 swildner Exp $
19 #include <sys/types.h>
21 #include <sys/ioctl.h>
22 #include <sys/disklabel.h>
23 #include <sys/diskslice.h>
24 #include <sys/diskmbr.h>
28 #define DOSPTYP_EXTENDED 5
32 #define DEF_INTERLEAVE 1
34 #define WHERE(offset,disk) (disk->flags & DISK_ON_TRACK ? offset + 63 : offset)
36 /* XXX: A lot of hardcoded 512s probably should be foo->sector_size;
37 I'm not sure which, so I leave it like it worked before. --schweikh */
39 Write_FreeBSD(int fd
, struct disk
*new, struct disk
*old
, struct chunk
*c1
)
47 for(i
= 0; i
< BBSIZE
/512; i
++) {
48 p
= read_block(fd
, WHERE(i
+ c1
->offset
, new), 512);
49 memcpy(buf
+ 512 * i
, p
, 512);
54 memcpy(buf
, new->boot1
, 512);
57 memcpy(buf
+ 512, new->boot2
, BBSIZE
-512);
60 dl
= (struct disklabel
*)(buf
+ 512 * LABELSECTOR
+ LABELOFFSET
);
61 memset(dl
, 0, sizeof *dl
);
63 for(c2
= c1
->part
; c2
; c2
= c2
->next
) {
64 if (c2
->type
== unused
) continue;
65 if (!strcmp(c2
->name
, "X")) continue;
66 j
= c2
->name
[strlen(new->name
) + 2] - 'a';
67 if (j
< 0 || j
>= MAXPARTITIONS
|| j
== RAW_PART
) {
69 warn("weird partition letter %c", c2
->name
[strlen(new->name
) + 2]);
73 dl
->d_partitions
[j
].p_size
= c2
->size
;
74 dl
->d_partitions
[j
].p_offset
= c2
->offset
;
75 dl
->d_partitions
[j
].p_fstype
= c2
->subtype
;
78 dl
->d_bbsize
= BBSIZE
;
80 * Add in defaults for superblock size, interleave, and rpms
82 dl
->d_sbsize
= SBSIZE
;
83 dl
->d_interleave
= DEF_INTERLEAVE
;
86 strcpy(dl
->d_typename
, c1
->name
);
89 dl
->d_secperunit
= new->chunks
->size
;
90 dl
->d_ncylinders
= new->bios_cyl
;
91 dl
->d_ntracks
= new->bios_hd
;
92 dl
->d_nsectors
= new->bios_sect
;
93 dl
->d_secpercyl
= dl
->d_ntracks
* dl
->d_nsectors
;
95 dl
->d_npartitions
= MAXPARTITIONS
;
97 dl
->d_type
= new->name
[0] == 's' || new->name
[0] == 'd' ||
98 new->name
[0] == 'o' ? DTYPE_SCSI
: DTYPE_ESDI
;
99 dl
->d_partitions
[RAW_PART
].p_size
= c1
->size
;
100 dl
->d_partitions
[RAW_PART
].p_offset
= c1
->offset
;
102 if(new->flags
& DISK_ON_TRACK
)
103 for(i
=0;i
<MAXPARTITIONS
;i
++)
104 if (dl
->d_partitions
[i
].p_size
)
105 dl
->d_partitions
[i
].p_offset
+= 63;
106 dl
->d_magic
= DISKMAGIC
;
107 dl
->d_magic2
= DISKMAGIC
;
108 dl
->d_checksum
= dkcksum(dl
);
110 for(i
=0;i
<BBSIZE
/512;i
++) {
111 write_block(fd
,WHERE(i
+ c1
->offset
, new), buf
+ 512 * i
, 512);
118 Write_Extended(int fd
, struct disk
*new, struct disk
*old
, struct chunk
*c1
)
123 #if defined(__i386__)
125 Write_Int32(u_int32_t
*p
, u_int32_t v
)
127 u_int8_t
*bp
= (u_int8_t
*)p
;
128 bp
[0] = (v
>> 0) & 0xff;
129 bp
[1] = (v
>> 8) & 0xff;
130 bp
[2] = (v
>> 16) & 0xff;
131 bp
[3] = (v
>> 24) & 0xff;
135 #if defined(__i386__)
137 * Special install-time configuration for the i386 boot0 boot manager.
140 Cfg_Boot_Mgr(u_char
*mbr
, int edd
)
142 if (mbr
[0x1b0] == 0x66 && mbr
[0x1b1] == 0xbb) {
144 mbr
[0x1bb] |= 0x80; /* Packet mode on */
146 mbr
[0x1bb] &= 0x7f; /* Packet mode off */
152 Write_Disk(struct disk
*d1
)
158 struct disk
*old
= 0;
163 struct dos_partition
*dp
,work
[NDOSPART
];
166 int need_edd
= 0; /* Need EDD (packet interface) */
171 strcpy(device
,_PATH_DEV
);
172 strcat(device
,d1
->name
);
174 fd
= open(device
,O_RDWR
);
177 warn("open(%s) failed", device
);
181 ioctl(fd
, DIOCWLABEL
, &one
);
183 memset(s
,0,sizeof s
);
184 mbr
= read_block(fd
, WHERE(0, d1
), d1
->sector_size
);
185 dp
= (struct dos_partition
*)(mbr
+ DOSPARTOFF
);
186 memcpy(work
, dp
, sizeof work
);
189 for (c1
= d1
->chunks
->part
; c1
; c1
= c1
->next
) {
190 if (c1
->type
== unused
) continue;
191 if (!strcmp(c1
->name
, "X")) continue;
193 j
= c1
->name
[4] - '1';
194 j
= c1
->name
[strlen(d1
->name
) + 1] - '1';
199 if (c1
->type
== extended
)
200 ret
+= Write_Extended(fd
, d1
, old
, c1
);
201 if (c1
->type
== freebsd
)
202 ret
+= Write_FreeBSD(fd
, d1
, old
, c1
);
205 Write_Int32(&dp
[j
].dp_start
, c1
->offset
);
206 Write_Int32(&dp
[j
].dp_size
, c1
->size
);
209 if (i
>= 1024*d1
->bios_sect
*d1
->bios_hd
) {
210 dp
[j
].dp_ssect
= 0xff;
212 dp
[j
].dp_scyl
= 0xff;
215 dp
[j
].dp_ssect
= i
% d1
->bios_sect
;
216 i
-= dp
[j
].dp_ssect
++;
218 dp
[j
].dp_shd
= i
% d1
->bios_hd
;
223 dp
[j
].dp_ssect
|= i
>> 2;
227 printf("S:%lu = (%x/%x/%x)",
228 c1
->offset
, dp
[j
].dp_scyl
, dp
[j
].dp_shd
, dp
[j
].dp_ssect
);
232 dp
[j
].dp_esect
= i
% d1
->bios_sect
;
233 i
-= dp
[j
].dp_esect
++;
235 dp
[j
].dp_ehd
= i
% d1
->bios_hd
;
238 if (i
>1023) i
= 1023;
241 dp
[j
].dp_esect
|= i
>> 2;
244 printf(" E:%lu = (%x/%x/%x)\n",
245 c1
->end
, dp
[j
].dp_ecyl
, dp
[j
].dp_ehd
, dp
[j
].dp_esect
);
248 dp
[j
].dp_typ
= c1
->subtype
;
249 if (c1
->flags
& CHUNK_ACTIVE
)
250 dp
[j
].dp_flag
= 0x80;
257 for(i
= 0; i
< NDOSPART
; i
++) {
259 memset(dp
+ i
, 0, sizeof *dp
);
264 for(i
= 0; i
< NDOSPART
; i
++)
265 if (dp
[i
].dp_typ
== 0xa5)
266 dp
[i
].dp_flag
= 0x80;
268 mbr
= read_block(fd
, WHERE(0, d1
), d1
->sector_size
);
270 memcpy(mbr
, d1
->bootmgr
, DOSPARTOFF
);
271 Cfg_Boot_Mgr(mbr
, need_edd
);
273 memcpy(mbr
+ DOSPARTOFF
, dp
, sizeof *dp
* NDOSPART
);
276 write_block(fd
, WHERE(0, d1
), mbr
, d1
->sector_size
);
277 if (d1
->bootmgr
&& d1
->bootmgr_size
> d1
->sector_size
)
278 for(i
= 1; i
* d1
->sector_size
<= d1
->bootmgr_size
; i
++)
279 write_block(fd
, WHERE(i
, d1
), &d1
->bootmgr
[i
* d1
->sector_size
], d1
->sector_size
);
283 i
= ioctl(fd
, DIOCSYNCSLICEINFO
, &i
);
286 warn("ioctl(DIOCSYNCSLICEINFO)");
288 ioctl(fd
, DIOCWLABEL
, &zero
);