1263409Smarcel/*-
2263409Smarcel * Copyright (c) 2014 Juniper Networks, Inc.
3263409Smarcel * All rights reserved.
4263409Smarcel *
5263409Smarcel * Redistribution and use in source and binary forms, with or without
6263409Smarcel * modification, are permitted provided that the following conditions
7263409Smarcel * are met:
8263409Smarcel * 1. Redistributions of source code must retain the above copyright
9263409Smarcel *    notice, this list of conditions and the following disclaimer.
10263409Smarcel * 2. Redistributions in binary form must reproduce the above copyright
11263409Smarcel *    notice, this list of conditions and the following disclaimer in the
12263409Smarcel *    documentation and/or other materials provided with the distribution.
13263409Smarcel *
14263409Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15263409Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16263409Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17263409Smarcel * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18263409Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19263409Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20263409Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21263409Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22263409Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23263409Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24263409Smarcel * SUCH DAMAGE.
25263409Smarcel */
26263409Smarcel
27263409Smarcel#include <sys/cdefs.h>
28263409Smarcel__FBSDID("$FreeBSD: releng/11.0/usr.bin/mkimg/pc98.c 272485 2014-10-03 20:48:11Z marcel $");
29263409Smarcel
30263409Smarcel#include <sys/types.h>
31263409Smarcel#include <sys/diskpc98.h>
32263697Smarcel#include <sys/endian.h>
33263442Smarcel#include <sys/errno.h>
34263409Smarcel#include <stdlib.h>
35263697Smarcel#include <string.h>
36263697Smarcel#include <unistd.h>
37263409Smarcel
38266176Smarcel#include "image.h"
39263409Smarcel#include "mkimg.h"
40263409Smarcel#include "scheme.h"
41263409Smarcel
42263923Smarcel#ifndef PC98_MAGIC
43263923Smarcel#define	PC98_MAGIC		0xaa55
44263923Smarcel#endif
45263923Smarcel#ifndef PC98_MAGICOFS
46263923Smarcel#define	PC98_MAGICOFS		510
47263923Smarcel#endif
48263923Smarcel#ifndef PC98_NPARTS
49263923Smarcel#define	PC98_NPARTS		16
50263923Smarcel#endif
51263923Smarcel#ifndef PC98_PTYP_386BSD
52263923Smarcel#define	PC98_PTYP_386BSD	0xc494
53263923Smarcel#endif
54263923Smarcel
55263697Smarcel#define	PC98_BOOTCODESZ		8192
56263697Smarcel
57263409Smarcelstatic struct mkimg_alias pc98_aliases[] = {
58263697Smarcel    {	ALIAS_FREEBSD, ALIAS_INT2TYPE(PC98_PTYP_386BSD) },
59263487Smarcel    {	ALIAS_NONE, 0 }
60263409Smarcel};
61263409Smarcel
62271881Smarcelstatic lba_t
63271881Smarcelpc98_metadata(u_int where, lba_t blk)
64263409Smarcel{
65271881Smarcel	if (where == SCHEME_META_IMG_START)
66271881Smarcel		blk += PC98_BOOTCODESZ / secsz;
67271881Smarcel	return (round_track(blk));
68263409Smarcel}
69263409Smarcel
70263697Smarcelstatic void
71272485Smarcelpc98_chs(u_short *cylp, u_char *hdp, u_char *secp, lba_t lba)
72263697Smarcel{
73272485Smarcel	u_int cyl, hd, sec;
74263697Smarcel
75272485Smarcel	mkimg_chs(lba, 0xffff, &cyl, &hd, &sec);
76272485Smarcel	le16enc(cylp, cyl);
77272485Smarcel	*hdp = hd;
78272485Smarcel	*secp = sec;
79263697Smarcel}
80263697Smarcel
81263442Smarcelstatic int
82266176Smarcelpc98_write(lba_t imgsz __unused, void *bootcode)
83263442Smarcel{
84263697Smarcel	struct part *part;
85263697Smarcel	struct pc98_partition *dpbase, *dp;
86263697Smarcel	u_char *buf;
87272485Smarcel	lba_t size;
88263697Smarcel	int error, ptyp;
89263697Smarcel
90263697Smarcel	buf = malloc(PC98_BOOTCODESZ);
91263697Smarcel	if (buf == NULL)
92263697Smarcel		return (ENOMEM);
93263697Smarcel	if (bootcode != NULL) {
94263697Smarcel		memcpy(buf, bootcode, PC98_BOOTCODESZ);
95263697Smarcel		memset(buf + secsz, 0, secsz);
96263697Smarcel	} else
97263697Smarcel		memset(buf, 0, PC98_BOOTCODESZ);
98263697Smarcel	le16enc(buf + PC98_MAGICOFS, PC98_MAGIC);
99263697Smarcel	dpbase = (void *)(buf + secsz);
100263697Smarcel	STAILQ_FOREACH(part, &partlist, link) {
101272485Smarcel		size = round_track(part->size);
102263697Smarcel		dp = dpbase + part->index;
103263697Smarcel		ptyp = ALIAS_TYPE2INT(part->type);
104263697Smarcel		dp->dp_mid = ptyp;
105263697Smarcel		dp->dp_sid = ptyp >> 8;
106263697Smarcel		pc98_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect,
107263697Smarcel		    part->block);
108263697Smarcel		pc98_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect,
109272485Smarcel		    part->block + size - 1);
110263697Smarcel		if (part->label != NULL)
111263697Smarcel			memcpy(dp->dp_name, part->label, strlen(part->label));
112263697Smarcel	}
113266176Smarcel	error = image_write(0, buf, PC98_BOOTCODESZ / secsz);
114263697Smarcel	free(buf);
115263697Smarcel	return (error);
116263442Smarcel}
117263442Smarcel
118263409Smarcelstatic struct mkimg_scheme pc98_scheme = {
119263409Smarcel	.name = "pc98",
120263409Smarcel	.description = "PC-9800 disk partitions",
121263409Smarcel	.aliases = pc98_aliases,
122263440Smarcel	.metadata = pc98_metadata,
123263442Smarcel	.write = pc98_write,
124263697Smarcel	.bootcode = PC98_BOOTCODESZ,
125263697Smarcel	.labellen = 16,
126263700Smarcel	.nparts = PC98_NPARTS,
127263700Smarcel	.maxsecsz = 512
128263409Smarcel};
129263409Smarcel
130263409SmarcelSCHEME_DEFINE(pc98_scheme);
131