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$");
29263409Smarcel
30263409Smarcel#include <sys/types.h>
31263409Smarcel#include <sys/apm.h>
32263656Smarcel#include <sys/endian.h>
33263442Smarcel#include <sys/errno.h>
34263409Smarcel#include <stdlib.h>
35263656Smarcel#include <string.h>
36263656Smarcel#include <unistd.h>
37263409Smarcel
38268161Smarcel#include "image.h"
39263409Smarcel#include "mkimg.h"
40263409Smarcel#include "scheme.h"
41263409Smarcel
42269177Smarcel#ifndef APM_ENT_TYPE_APPLE_BOOT
43269177Smarcel#define	APM_ENT_TYPE_APPLE_BOOT		"Apple_Bootstrap"
44269177Smarcel#endif
45268161Smarcel#ifndef APM_ENT_TYPE_FREEBSD_NANDFS
46268161Smarcel#define	APM_ENT_TYPE_FREEBSD_NANDFS	"FreeBSD-nandfs"
47268161Smarcel#endif
48268161Smarcel
49263409Smarcelstatic struct mkimg_alias apm_aliases[] = {
50263656Smarcel    {	ALIAS_FREEBSD, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD) },
51268161Smarcel    {	ALIAS_FREEBSD_BOOT, ALIAS_PTR2TYPE(APM_ENT_TYPE_APPLE_BOOT) },
52263656Smarcel    {	ALIAS_FREEBSD_NANDFS, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD_NANDFS) },
53263656Smarcel    {	ALIAS_FREEBSD_SWAP, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD_SWAP) },
54263656Smarcel    {	ALIAS_FREEBSD_UFS, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD_UFS) },
55263656Smarcel    {	ALIAS_FREEBSD_VINUM, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD_VINUM) },
56263656Smarcel    {	ALIAS_FREEBSD_ZFS, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD_ZFS) },
57263487Smarcel    {	ALIAS_NONE, 0 }
58263409Smarcel};
59263409Smarcel
60272030Smarcelstatic lba_t
61272030Smarcelapm_metadata(u_int where, lba_t blk)
62263409Smarcel{
63263409Smarcel
64272030Smarcel	blk += (where == SCHEME_META_IMG_START) ? nparts + 2 : 0;
65272030Smarcel	return (round_block(blk));
66263409Smarcel}
67263409Smarcel
68263442Smarcelstatic int
69268161Smarcelapm_write(lba_t imgsz, void *bootcode __unused)
70263442Smarcel{
71263656Smarcel	u_char *buf;
72263656Smarcel	struct apm_ddr *ddr;
73263656Smarcel	struct apm_ent *ent;
74263656Smarcel	struct part *part;
75263656Smarcel	int error;
76263656Smarcel
77263656Smarcel	buf = calloc(nparts + 2, secsz);
78263656Smarcel	if (buf == NULL)
79263656Smarcel		return (ENOMEM);
80263656Smarcel	ddr = (void *)buf;
81263656Smarcel	be16enc(&ddr->ddr_sig, APM_DDR_SIG);
82263656Smarcel	be16enc(&ddr->ddr_blksize, secsz);
83263656Smarcel	be32enc(&ddr->ddr_blkcount, imgsz);
84263656Smarcel
85263656Smarcel	/* partition entry for the partition table itself. */
86263656Smarcel	ent = (void *)(buf + secsz);
87263656Smarcel	be16enc(&ent->ent_sig, APM_ENT_SIG);
88263656Smarcel	be32enc(&ent->ent_pmblkcnt, nparts + 1);
89263656Smarcel	be32enc(&ent->ent_start, 1);
90263656Smarcel	be32enc(&ent->ent_size, nparts + 1);
91268161Smarcel	strncpy(ent->ent_type, APM_ENT_TYPE_SELF, sizeof(ent->ent_type));
92268161Smarcel	strncpy(ent->ent_name, "Apple", sizeof(ent->ent_name));
93263656Smarcel
94263656Smarcel	STAILQ_FOREACH(part, &partlist, link) {
95263656Smarcel		ent = (void *)(buf + (part->index + 2) * secsz);
96263656Smarcel		be16enc(&ent->ent_sig, APM_ENT_SIG);
97263656Smarcel		be32enc(&ent->ent_pmblkcnt, nparts + 1);
98263656Smarcel		be32enc(&ent->ent_start, part->block);
99263656Smarcel		be32enc(&ent->ent_size, part->size);
100268161Smarcel		strncpy(ent->ent_type, ALIAS_TYPE2PTR(part->type),
101268161Smarcel		    sizeof(ent->ent_type));
102263656Smarcel		if (part->label != NULL)
103268161Smarcel			strncpy(ent->ent_name, part->label,
104268161Smarcel			    sizeof(ent->ent_name));
105263656Smarcel	}
106263656Smarcel
107268161Smarcel	error = image_write(0, buf, nparts + 2);
108263656Smarcel	free(buf);
109263656Smarcel	return (error);
110263442Smarcel}
111263442Smarcel
112263409Smarcelstatic struct mkimg_scheme apm_scheme = {
113263409Smarcel	.name = "apm",
114263409Smarcel	.description = "Apple Partition Map",
115263409Smarcel	.aliases = apm_aliases,
116263440Smarcel	.metadata = apm_metadata,
117263442Smarcel	.write = apm_write,
118263656Smarcel	.nparts = 4096,
119263700Smarcel	.labellen = APM_ENT_NAMELEN - 1,
120263700Smarcel	.maxsecsz = 4096
121263409Smarcel};
122263409Smarcel
123263409SmarcelSCHEME_DEFINE(apm_scheme);
124