1 /* $NetBSD: winblk.c,v 1.8 2009/03/14 15:36:07 dsl Exp $ */
4 * Copyright (c) 1999 Shin Takemura.
7 * This software is part of the PocketBSD.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the PocketBSD project
20 * and its contributors.
21 * 4. Neither the name of the project nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #define STANDALONE_WINDOWS_SIDE
42 #include <sys/disklabel.h>
47 * DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,
48 * LPVOID lpInBuffer, DWORD nInBufferSize,
49 * LPVOID lpOutBuffer, DWORD nOutBufferSize,
50 * LPDWORD lpBytesReturned,
51 * LPOVERLAPPED lpOverlapped);
55 #define DEBUG_PRINTF(a) win_printf a
57 #define DEBUG_PRINTF(a)
60 #define islower(c) ('a' <= (c) && (c) <= 'z')
61 #define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
68 struct mbr_partition mbr
[MBR_PART_COUNT
];
74 static int rawread(struct winblk
*ctx
, int start
, int nsecs
, char *buf
);
77 winblkstrategy(void *devdata
, int flag
, daddr_t dblk
, size_t size
, void *buf
, size_t *rsize
)
79 struct winblk
*ctx
= (struct winblk
*)devdata
;
87 nblks
= (size
/ BLKSZ
);
89 if (error
= rawread(ctx
, dblk
, nblks
, buf
)) {
92 if (nblks
* BLKSZ
< size
) {
93 if (error
= rawread(ctx
, dblk
+ nblks
, 1, ctx
->buf
)) {
96 memcpy((BYTE
*)buf
+ nblks
* BLKSZ
, ctx
->buf
,
97 size
- nblks
* BLKSZ
);
107 winblkopen(struct open_file
*f
, ...)
108 /* file, devname, unit, partition */
111 struct winblk
*ctx
= NULL
;
122 ctx
= (struct winblk
*)alloc(sizeof(*ctx
));
130 devname
= va_arg(ap
, char*);
131 unit
= va_arg(ap
, int);
132 partition
= va_arg(ap
, int);
136 * Windows' device name must be 3 uppper letters and 1 digit
137 * following a semicolon like "DSK1:".
139 if (strlen(devname
) != 3 || unit
< 0 || 9 < unit
) {
143 wsprintf(wdevname
, TEXT("%C%C%C%d:"),
148 DEBUG_PRINTF((TEXT("winblk.open: block device name is '%s'\n"),
151 ctx
->hDevice
= CreateFile(wdevname
, GENERIC_READ
, 0, NULL
,
152 OPEN_EXISTING
, 0, NULL
);
153 if (ctx
->hDevice
== INVALID_HANDLE_VALUE
) {
154 win_printf(TEXT("can't open %s.\n"), wdevname
);
155 error
= ENODEV
; /* XXX, We shuld check GetLastError(). */
161 * CHS, sector size and device flags.
163 if (!DeviceIoControl(ctx
->hDevice
, DISK_IOCTL_GETINFO
,
164 &ctx
->di
, sizeof(ctx
->di
),
165 NULL
, 0, &wres
, NULL
)) {
166 win_printf(TEXT("DeviceIoControl() failed.error=%d\n"),
169 error
= EIO
; /* XXX, We shuld check GetLastError(). */
174 win_printf(TEXT("DISK_INFO: CHS=%d:%d:%d block size=%d flag="),
175 ctx
->di
.di_cylinders
,
178 ctx
->di
.di_bytes_per_sect
);
179 if (ctx
->di
.di_flags
& DISK_INFO_FLAG_MBR
) {
180 win_printf(TEXT("MBR "));
182 if (ctx
->di
.di_flags
& DISK_INFO_FLAG_CHS_UNCERTAIN
) {
183 win_printf(TEXT("CHS_UNCERTAIN "));
185 if (ctx
->di
.di_flags
& DISK_INFO_FLAG_UNFORMATTED
) {
186 win_printf(TEXT("UNFORMATTED "));
188 if (ctx
->di
.di_flags
& DISK_INFO_FLAG_PAGEABLE
) {
189 win_printf(TEXT("PAGEABLE "));
191 win_printf(TEXT("\n"));
194 if (!(ctx
->di
.di_flags
& DISK_INFO_FLAG_MBR
) ||
195 (ctx
->di
.di_flags
& DISK_INFO_FLAG_CHS_UNCERTAIN
) ||
196 (ctx
->di
.di_flags
& DISK_INFO_FLAG_UNFORMATTED
) ||
197 (ctx
->di
.di_bytes_per_sect
!= BLKSZ
)) {
198 win_printf(TEXT("invalid flags\n"));
206 if (error
= rawread(ctx
, MBR_BBSECTOR
, 1, ctx
->buf
)) {
209 memcpy(&ctx
->mbr
, &ctx
->buf
[MBR_PART_OFFSET
], sizeof(ctx
->mbr
));
211 for (i
= 0; i
< MBR_PART_COUNT
; i
++) {
212 DEBUG_PRINTF((TEXT("%d: type=%d %d(%d) (%d:%d:%d - %d:%d:%d)")
213 TEXT(" flag=0x%02x\n"),
215 ctx
->mbr
[i
].mbrp_type
,
216 ctx
->mbr
[i
].mbrp_start
,
217 ctx
->mbr
[i
].mbrp_size
,
218 ctx
->mbr
[i
].mbrp_scyl
,
219 ctx
->mbr
[i
].mbrp_shd
,
220 ctx
->mbr
[i
].mbrp_ssect
,
221 ctx
->mbr
[i
].mbrp_ecyl
,
222 ctx
->mbr
[i
].mbrp_ehd
,
223 ctx
->mbr
[i
].mbrp_esect
,
224 ctx
->mbr
[i
].mbrp_flag
));
232 for (i
= 0; i
< MBR_PART_COUNT
; i
++) {
233 if (ctx
->mbr
[i
].mbrp_type
== MBR_PTYPE_NETBSD
) {
234 ctx
->start
= ctx
->mbr
[i
].mbrp_start
;
237 if (ctx
->mbr
[i
].mbrp_type
== MBR_PTYPE_386BSD
) {
238 start_386bsd
= ctx
->mbr
[i
].mbrp_start
;
241 if (ctx
->start
== -1) {
242 ctx
->start
= start_386bsd
;
245 if (ctx
->start
== -1) {
247 * BSD partition is not found.
248 * Try to use entire disk.
251 win_printf(TEXT("no BSD partition, start sector=0x%x\n"),
259 if (error
= rawread(ctx
, ctx
->start
+ LABELSECTOR
, 1, ctx
->buf
)) {
262 memcpy(&ctx
->dl
, &ctx
->buf
[LABELOFFSET
], sizeof(ctx
->dl
));
264 if (ctx
->dl
.d_magic
!= DISKMAGIC
||
265 ctx
->dl
.d_magic2
!= DISKMAGIC
||
266 dkcksum(&ctx
->dl
) != 0) {
267 win_printf(TEXT("invalid disklabel, start sector=0x%x\n"),
270 * Disklabel is not found.
271 * Try to use entire partition.
276 if (partition
< 0 || ctx
->dl
.d_npartitions
<= partition
) {
281 ctx
->start
= ctx
->dl
.d_partitions
[partition
].p_offset
;
282 win_printf(TEXT("start sector=0x%x\n"), ctx
->start
);
286 dealloc(ctx
, sizeof(*ctx
));
293 winblkclose(struct open_file
*f
)
295 struct winblk
*ctx
= f
->f_devdata
;
297 dealloc(ctx
, sizeof(*ctx
));
304 winblkioctl(struct open_file
*f
, u_long cmd
, void *arg
)
310 rawread(struct winblk
*ctx
, int start
, int nsecs
, char *buf
)
315 req
.sr_start
= start
;
316 req
.sr_num_sec
= nsecs
;
318 req
.sr_callback
= NULL
;
319 req
.sr_sglist
[0].sb_buf
= buf
;
320 req
.sr_sglist
[0].sb_len
= nsecs
* BLKSZ
;
322 DEBUG_PRINTF((TEXT("rawread(0x%x, %d)"), start
, nsecs
));
323 if (!DeviceIoControl(ctx
->hDevice
, DISK_IOCTL_READ
,
325 NULL
, 0, &res
, NULL
)) {
326 win_printf(TEXT("DeviceIoControl() failed.error=%d\n"),
329 return (EIO
); /* XXX, We shuld check GetLastError(). */
331 DEBUG_PRINTF((TEXT("=%d\n"), req
.sr_status
));
333 if (req
.sr_status
!= ERROR_SUCCESS
) {
334 win_printf(TEXT("DeviceIoControl(READ): status=%d\n"),
336 return (EIO
); /* XXX, We shuld check error code. */