1 /* $NetBSD: winblk.c,v 1.4 2005/12/11 12:17:30 christos 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
,
78 void *buf
, size_t *rsize
)
80 struct winblk
*ctx
= (struct winblk
*)devdata
;
88 nblks
= (size
/ BLKSZ
);
90 if (error
= rawread(ctx
, dblk
, nblks
, buf
)) {
93 if (nblks
* BLKSZ
< size
) {
94 if (error
= rawread(ctx
, dblk
+ nblks
, 1, ctx
->buf
)) {
97 memcpy((BYTE
*)buf
+ nblks
* BLKSZ
, ctx
->buf
,
98 size
- nblks
* BLKSZ
);
108 winblkopen(struct open_file
*f
, ...)
109 /* file, devname, unit, partition */
112 struct winblk
*ctx
= NULL
;
123 ctx
= (struct winblk
*)alloc(sizeof(*ctx
));
131 devname
= va_arg(ap
, char*);
132 unit
= va_arg(ap
, int);
133 partition
= va_arg(ap
, int);
137 * Windows' device name must be 3 uppper letters and 1 digit
138 * following a semicolon like "DSK1:".
140 if (strlen(devname
) != 3 || unit
< 0 || 9 < unit
) {
144 wsprintf(wdevname
, TEXT("%C%C%C%d:"),
149 DEBUG_PRINTF((TEXT("winblk.open: block device name is '%s'\n"),
152 ctx
->hDevice
= CreateFile(wdevname
, GENERIC_READ
, 0, NULL
,
153 OPEN_EXISTING
, 0, NULL
);
154 if (ctx
->hDevice
== INVALID_HANDLE_VALUE
) {
155 win_printf(TEXT("can't open %s.\n"), wdevname
);
156 error
= ENODEV
; /* XXX, We shuld check GetLastError(). */
162 * CHS, sector size and device flags.
164 if (!DeviceIoControl(ctx
->hDevice
, DISK_IOCTL_GETINFO
,
165 &ctx
->di
, sizeof(ctx
->di
),
166 NULL
, 0, &wres
, NULL
)) {
167 win_printf(TEXT("DeviceIoControl() failed.error=%d\n"),
170 error
= EIO
; /* XXX, We shuld check GetLastError(). */
175 win_printf(TEXT("DISK_INFO: CHS=%d:%d:%d block size=%d flag="),
176 ctx
->di
.di_cylinders
,
179 ctx
->di
.di_bytes_per_sect
);
180 if (ctx
->di
.di_flags
& DISK_INFO_FLAG_MBR
) {
181 win_printf(TEXT("MBR "));
183 if (ctx
->di
.di_flags
& DISK_INFO_FLAG_CHS_UNCERTAIN
) {
184 win_printf(TEXT("CHS_UNCERTAIN "));
186 if (ctx
->di
.di_flags
& DISK_INFO_FLAG_UNFORMATTED
) {
187 win_printf(TEXT("UNFORMATTED "));
189 if (ctx
->di
.di_flags
& DISK_INFO_FLAG_PAGEABLE
) {
190 win_printf(TEXT("PAGEABLE "));
192 win_printf(TEXT("\n"));
195 if (!(ctx
->di
.di_flags
& DISK_INFO_FLAG_MBR
) ||
196 (ctx
->di
.di_flags
& DISK_INFO_FLAG_CHS_UNCERTAIN
) ||
197 (ctx
->di
.di_flags
& DISK_INFO_FLAG_UNFORMATTED
) ||
198 (ctx
->di
.di_bytes_per_sect
!= BLKSZ
)) {
199 win_printf(TEXT("invalid flags\n"));
207 if (error
= rawread(ctx
, MBR_BBSECTOR
, 1, ctx
->buf
)) {
210 memcpy(&ctx
->mbr
, &ctx
->buf
[MBR_PART_OFFSET
], sizeof(ctx
->mbr
));
212 for (i
= 0; i
< MBR_PART_COUNT
; i
++) {
213 DEBUG_PRINTF((TEXT("%d: type=%d %d(%d) (%d:%d:%d - %d:%d:%d)")
214 TEXT(" flag=0x%02x\n"),
216 ctx
->mbr
[i
].mbrp_type
,
217 ctx
->mbr
[i
].mbrp_start
,
218 ctx
->mbr
[i
].mbrp_size
,
219 ctx
->mbr
[i
].mbrp_scyl
,
220 ctx
->mbr
[i
].mbrp_shd
,
221 ctx
->mbr
[i
].mbrp_ssect
,
222 ctx
->mbr
[i
].mbrp_ecyl
,
223 ctx
->mbr
[i
].mbrp_ehd
,
224 ctx
->mbr
[i
].mbrp_esect
,
225 ctx
->mbr
[i
].mbrp_flag
));
233 for (i
= 0; i
< MBR_PART_COUNT
; i
++) {
234 if (ctx
->mbr
[i
].mbrp_type
== MBR_PTYPE_NETBSD
) {
235 ctx
->start
= ctx
->mbr
[i
].mbrp_start
;
238 if (ctx
->mbr
[i
].mbrp_type
== MBR_PTYPE_386BSD
) {
239 start_386bsd
= ctx
->mbr
[i
].mbrp_start
;
242 if (ctx
->start
== -1) {
243 ctx
->start
= start_386bsd
;
246 if (ctx
->start
== -1) {
248 * BSD partition is not found.
249 * Try to use entire disk.
252 win_printf(TEXT("no BSD partition, start sector=0x%x\n"),
260 if (error
= rawread(ctx
, ctx
->start
+ LABELSECTOR
, 1, ctx
->buf
)) {
263 memcpy(&ctx
->dl
, &ctx
->buf
[LABELOFFSET
], sizeof(ctx
->dl
));
265 if (ctx
->dl
.d_magic
!= DISKMAGIC
||
266 ctx
->dl
.d_magic2
!= DISKMAGIC
||
267 dkcksum(&ctx
->dl
) != 0) {
268 win_printf(TEXT("invalid disklabel, start sector=0x%x\n"),
271 * Disklabel is not found.
272 * Try to use entire partition.
277 if (partition
< 0 || ctx
->dl
.d_npartitions
<= partition
) {
282 ctx
->start
= ctx
->dl
.d_partitions
[partition
].p_offset
;
283 win_printf(TEXT("start sector=0x%x\n"), ctx
->start
);
287 dealloc(ctx
, sizeof(*ctx
));
294 winblkclose(struct open_file
*f
)
296 struct winblk
*ctx
= f
->f_devdata
;
298 dealloc(ctx
, sizeof(*ctx
));
305 winblkioctl(struct open_file
*f
, u_long cmd
, void *arg
)
311 rawread(struct winblk
*ctx
, int start
, int nsecs
, char *buf
)
316 req
.sr_start
= start
;
317 req
.sr_num_sec
= nsecs
;
319 req
.sr_callback
= NULL
;
320 req
.sr_sglist
[0].sb_buf
= buf
;
321 req
.sr_sglist
[0].sb_len
= nsecs
* BLKSZ
;
323 DEBUG_PRINTF((TEXT("rawread(0x%x, %d)"), start
, nsecs
));
324 if (!DeviceIoControl(ctx
->hDevice
, DISK_IOCTL_READ
,
326 NULL
, 0, &res
, NULL
)) {
327 win_printf(TEXT("DeviceIoControl() failed.error=%d\n"),
330 return (EIO
); /* XXX, We shuld check GetLastError(). */
332 DEBUG_PRINTF((TEXT("=%d\n"), req
.sr_status
));
334 if (req
.sr_status
!= ERROR_SUCCESS
) {
335 win_printf(TEXT("DeviceIoControl(READ): status=%d\n"),
337 return (EIO
); /* XXX, We shuld check error code. */