* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: mem.c
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
#pragma ident "@(#)mem.c 1.24 07/04/16 SMI"
* Complete the parsing of a generic memory device.
* Pick out the relevent info and allocated the
* simcpu_t structure in the config_cpu that
#if VDISK_SUPPORT /* { */
#endif /* VDISK_SUPPORT } */
* static only to avoid name clashes with other
* modules ... in reality these are exported
* via the cpu_type_t struct pointers
static void mem_parse(config_dev_t
*);
static void mem_init(config_dev_t
*);
static void mem_dump(config_dev_t
*);
static tpaddr_t
mem_cacheable(config_addr_t
*, dev_access_t type
,
tpaddr_t off
, uint8_t **cbp
);
static bool_t
mem_cpu_access(simcpu_t
*, config_addr_t
*, tpaddr_t off
,
maccess_t op
, uint64_t *regp
);
dev_type_t dev_type_memory
= {
mem_cpu_access
, /* shouldnt be called if we're a RAM */
typedef struct MEM_CONTENT mem_content_t
;
uint64_t fileextent
; /* how much of file to load in */
uint64_t fileextenta
; /* page alligned fileextent */
uint64_t fileoffset
; /* offset in file to start loading */
uint64_t memoffset
; /* offset in memory of where to load */
#if VDISK_SUPPORT /* { */
int disk_slice
; /* 0-1,3-7 (2 resvd for entire disk) */
#endif /* VDISK_SUPPORT } */
bool_t is_rom
; /* mmap disk with MAP_PRIVATE flag */
bool_t is_shared
; /* mmap disk with MAP_SHARED flag */
bool_t is_rom
; /* mmap file with MAP_PRIVATE flag */
bool_t is_shared
; /* mmap file with MAP_SHARED flag */
#if VDISK_SUPPORT /* { */
bool_t is_disk
; /* used to identify virtual disk */
#endif /* VDISK_SUPPORT } */
uint64_t size
; /* size of memory segment */
mem_content_t
*contentp
; /* Any content to manually add */
int nfileblocks
; /* no of files to load into segment */
mem_file_t fileblock
[1]; /* fileblock struct per file */
#if VDISK_SUPPORT /* { */
* local functions for manipulating disk labels
static void create_label(mem_dev_t
*mdp
);
static void dump_label(mem_dev_t
*mdp
);
static short get_checksum(struct dk_label
*dkl
, int mode
);
#endif /* VDISK_SUPPORT } */
static void mem_parse_content(mem_dev_t
*mdp
);
* Complete the creation and parsing of the memory directives
* Format for parsing internal memory data is:
* [rom | shared | virtual_disk]
* if a 'rom | shared' directive is found, we parse as follows:
* load [[+]addr] "filename" [ file_offset [ extent_to_load ] ]
* - ROM can only be specified once, we can have as many
* load directives as we like !
* if a 'virtual_disk' directive is found, we parse as follows:
* load s0 [rom|shared] "filename"
* load s1 [rom|shared] "filename"
* - We will figure out the size of the entire disk by opening each
* file. It's important that the first disk contains a valid
* VTOC at block 0. We will update the mmapped copy of this VTOC
* with the virtual partition information of all disks in the
* - You cannot specify a disk to load into s2 as that is reserved
* to describe the entire disk.
* - You can load disks into s0 (boot disk), s1 (swap),
* s3,s4,s5,s6,s7 (user specified mount points).
* - Each disk will be mmapped with the permissions specified in
mem_parse(config_dev_t
*config_devp
)
uint64_t memory_segment_size
; /* initial value of mdp->size */
* Allocate the memory device and all that stuff
mdp
= Xcalloc(1, mem_dev_t
);
#if VDISK_SUPPORT /* { */
#endif /* VDISK_SUPPORT } */
mdp
->contentp
= (mem_content_t
*)0;
mdp
->size
= config_devp
->addrp
->range
;
DBG( PRINTF(("mem_parse: parsing device %d\n", config_devp
->device_id
)); );
goto finished
; /* nothing more to parse */
lex_fatal("expecting either ; or { when parsing memory device");
uint64_t startoffset
= 0LL;
#if VDISK_SUPPORT /* { */
#endif /* VDISK_SUPPORT } */
bool_t is_shared
, is_rom
;
if (tok
== T_R_Brace
) break;
lex_fatal("expected load, rom, shared or virtual_disk "
"directive parsing memory device");
if (streq(lex
.strp
, "rom")) {
if (mdp
->is_rom
) lex_fatal("rom already specified");
if (streq(lex
.strp
, "shared")) {
lex_fatal("shared already specified");
if (streq(lex
.strp
, "virtual_disk")) {
#if VDISK_SUPPORT /* { */
lex_fatal("virtual_disk already specified");
* For disks, we don't need the size as specified in the
* conf file. We'll calculate the real size once we've
* found the size of all disks loaded.
* Howvever, we need to ensure that the memory segment
* used for mmapping the disks does not overlap with
* any other memory segment in use. Legion has already
* done this check when parsing the memory directive.
* We have gotten here if we have not overlapped. The
* concern now is that when we parse the disk directives
* we may extend beyond the memory segment specified by
* the memory directive. So as a check, we save the size
* here and run a check at the end to ensure that the
* total size of all disks is within the bounds of the
* size of the memory segment.
memory_segment_size
= mdp
->size
;
mdp
->size
= 0; /* We'll calculate this as we parse */
#else /* VDISK_SUPPORT } { */
lex_fatal("virtual_disk not supported on this "
#endif /* VDISK_SUPPORT } */
if (streq(lex
.strp
, "content")) {
if (!streq(lex
.strp
, "load")) goto fail
;
#if VDISK_SUPPORT /* { */
* Parse disk directive as follows:
* s(n) rom|shared "disk.name"
* - s(n) is the slice number (cannot be s2)
* - rom or shared to specify how to mmap this disk
* - "disk.name" you can probably guess ...
* NOTE: The VTOC of s0 will be overwritten in memory
* to with the correct label for all partitions
* that make up this virtual disk.
* s2 of the VTOC will contain the entire size
* of all mmapped disks. We also need a valid
* disk label checksum so OBP can open this disk.
* figure out which slice number this disk is
if (streq(lex
.strp
, "s0"))
else if (streq(lex
.strp
, "s1"))
else if (streq(lex
.strp
, "s2"))
lex_fatal("Cannot load a disk as slice 2.");
else if (streq(lex
.strp
, "s3"))
else if (streq(lex
.strp
, "s4"))
else if (streq(lex
.strp
, "s5"))
else if (streq(lex
.strp
, "s6"))
else if (streq(lex
.strp
, "s7"))
lex_fatal("expected a slice number of format "
* parse the mmap permissions for this disk
is_rom
= is_shared
= false;
if (streq(lex
.strp
, "rom"))
else if (streq(lex
.strp
, "shared"))
lex_fatal("expected either rom or shared");
fnamep
= Xstrdup(lex
.strp
);
lex_fatal("expected ; after filename");
#endif /* VDISK_SUPPORT } */
* Get the load offset, ie. the offset from the base
* address to load this file. For disk devices, we
* don't need this as we use the size of the previous
* disk to work out where to load the next disk.
if (lex
.val
< config_devp
->addrp
->baseaddr
||
lex
.val
>= config_devp
->addrp
->topaddr
)
lex_fatal("specified load address is outside "
"the range of the memory device");
startoffset
= lex
.val
- config_devp
->addrp
->baseaddr
;
lex_fatal("Expected either a start address / offset "
"or filename for memory device load directive");
fnamep
= Xstrdup(lex
.strp
);
lex_fatal("Expected ; or file offset for memory device "
lex_fatal("load file offset must be >0 for load directive");
lex_fatal("Expected ; or load length for memory device "
lex_fatal("load length must be >=0 for load directive");
if (stat(fnamep
, &sb
) < 0)
lex_fatal("error opening load file %s", fnamep
);
flen
= sb
.st_size
- foffset
;
#if VDISK_SUPPORT /* { */
* Set the load address of this disk slice (startoffset)
* to be right after the address that the previous
* slice loaded at (mdp->size)
* Increase the size of the disk by flen (rounded up
* so it's page aligned.) The next slice (if any)
* will be loaded at mdp->size.
mdp
->size
+= sim_roundup(flen
, pgsize
);
* sanity check to see if we've blown passed the
* the memory segment as specified in the conf
if (mdp
->size
> memory_segment_size
) {
printf("\n Memory segment overflow. "
mdp
->size
, memory_segment_size
);
lex_fatal("memory segment for disks has "
"extended beyond that specified in the "
#endif /* VDISK_SUPPORT } */
if (sb
.st_size
< (foffset
+ flen
))
lex_fatal("load file %s is smaller than the specified "
if ((startoffset
+ flen
) > config_devp
->addrp
->range
)
lex_fatal("load file %s is larger than the memory device",
/* OK have parsed file info - add it to load block */
idx
= mdp
->nfileblocks
++;
mdp
= Xrealloc(mdp
, Sizeof(mem_dev_t
) + mdp
->nfileblocks
* Sizeof(mem_file_t
));
mdp
->fileblock
[idx
].fnamep
= fnamep
;
/* how much of file to load in */
mdp
->fileblock
[idx
].fileextent
= flen
;
mdp
->fileblock
[idx
].fileextenta
= sim_roundup(flen
, pgsize
);
/* offset in file to start load */
mdp
->fileblock
[idx
].fileoffset
= foffset
;
/* offset in mem to start load */
mdp
->fileblock
[idx
].memoffset
= startoffset
;
/* MMAP with flag MAP_SHARED */
mdp
->fileblock
[idx
].is_shared
= is_shared
;
/* MMAP with flag MAP_PRIVATE */
mdp
->fileblock
[idx
].is_rom
= is_rom
;
#if VDISK_SUPPORT /* { */
/* disk partition number */
mdp
->fileblock
[idx
].disk_slice
= disk_slice
;
DBG( PRINTF(("\nPartition Info:::\nname: %s \nslice=%d "
"\nstartoffset = %llx \nflen = %llx \nfoffset = %llx "
"\nmdp->size = 0x%llx\nfilextent = 0x%llx "
"\nmemoffset = 0x%llx\n", mdp
->fileblock
[idx
].fnamep
,
mdp
->fileblock
[idx
].disk_slice
,
config_devp
->addrp
->baseaddr
,
startoffset
, flen
, foffset
, mdp
->size
,
mdp
->fileblock
[idx
].fileextent
,
mdp
->fileblock
[idx
].fileextenta
,
mdp
->fileblock
[idx
].memoffset
)); );
#endif /* VDISK_SUPPORT } */
mem_insert(mem_dev_t
*mdp
, uint64_t offset
, uint64_t size
, uint8_t *datap
)
mem_content_t
*tp
, **tpp
;
DBG( PRINTF(("mem_insert:offset: 0x%llx size: 0x%llx\n", offset
, size
)); );
/* walk the list looking for insertion point */
for (tpp
= &mdp
->contentp
; (tp
= *tpp
) != NULL
; tpp
= &tp
->nextp
) {
if (offset
< tp
->offset
) {
if ((offset
+ size
) > tp
->offset
) {
return (-1); /* overlap */
if ((tp
->offset
+ tp
->size
) > offset
) {
return (-1); /* overlap */
/* found the location, add the mem object */
tp
= Xcalloc(1, mem_content_t
);
* Handle the content directive
mem_parse_content(mem_dev_t
*mdp
)
if (offset
> mdp
->size
) lex_fatal("Offset is outside memory range");
word_size
= (int)lex
.val
;
mask
= 0xffffffffffffffffull
;
lex_fatal("Word size must be 8, 16, 32 or 64 bits");
while ((tok
= lex_get_token()) != T_R_Brace
) {
if (tok
!= T_Number
) lex_fatal("Unexpected content");
if ((lex
.val
& ~mask
) != 0LL) lex_fatal("Content out of range");
if (offset
+idx
+word_size
>= mdp
->size
)
lex_fatal("Content overflows memory range");
if (space
<= (idx
+word_size
)) {
datap
= Xrealloc(datap
, space
);
/* ensure it's written big-endian */
datap
[idx
] = (lex
.val
>> 56);
datap
[idx
+1] = (lex
.val
>> 48);
datap
[idx
+2] = (lex
.val
>> 40);
datap
[idx
+3] = (lex
.val
>> 32);
datap
[idx
] = (lex
.val
>> 24);
datap
[idx
+1] = (lex
.val
>> 16);
datap
[idx
] = (lex
.val
>> 8);
if (idx
== 0) lex_fatal("content directive must have some content");
if (mem_insert(mdp
, offset
, idx
, datap
) < 0) {
lex_fatal("Memory content overlap detected ");
* Initialise the mem after parsing is complete
* If no files have been requested, then we force a
* ... this is why the additional files start at
mem_init(config_dev_t
*config_devp
)
mem_content_t
*cp
, *next_cp
;
mdp
= (mem_dev_t
*)config_devp
->devp
;
* Perform a check to see that the requested loaded files are
* a) correctly aligned, and
* b) whether we need a /dev/zero mapping to back sections not
* covered by other mmapped files (beginning, middle,
* end), or because we need to "load" files in that are
* For the moment we create a MAP_ANON block of the entire
* ram/rom then map over than any additional data files we need.
* Force a segv if we ever try and write to a "ROM".
DBG( PRINTF(("memory mapping : 0x%llx\n", sim_roundup(mdp
->size
, pgsize
))); );
datap
= mdp
->datap
= (void*)mmap(NULL
, sim_roundup(mdp
->size
, pgsize
),
PROT_READ
| (mdp
->is_rom
? 0 : PROT_WRITE
),
MAP_PRIVATE
| MAP_ANON
| MAP_NORESERVE
, -1, 0);
if (MAP_FAILED
== datap
) fatal("Initial mmap of anon memory failed");
* Now we either map or load in all the remaining files that the
* config file may have specified.
for (idx
= 0; idx
< mdp
->nfileblocks
; idx
++) {
bool_t is_shared
= mdp
->is_shared
;
#if VDISK_SUPPORT /* { */
* Figure out which 'is_shared' to use, if we have a
* disk then each partition can have it's own flags
is_shared
= mdp
->fileblock
[idx
].is_shared
;
#endif /* VDISK_SUPPORT } */
fd
= open(mdp
->fileblock
[idx
].fnamep
,
is_shared
? O_RDWR
: O_RDONLY
);
} while (fd
< 0 && EAGAIN
== errno
);
fatal("Failed opening file %s",
mdp
->fileblock
[idx
].fnamep
);
* Check that the fileoffset (offset in file to start
* loading) is page alligned
if ((mdp
->fileblock
[idx
].fileoffset
% pgsize
) != 0)
fatal("Offset 0x%llx in file %s is not aligned "
mdp
->fileblock
[idx
].fileoffset
,
mdp
->fileblock
[idx
].fnamep
,
/* Allow non-rounded out contents */
if ((mdp
->fileblock
[idx
].fileextent
% pgsize
) != 0)
fatal("Loaded extent 0x%llx for file %s is not "
"aligned with 0x%llx pagesize",
mdp
->fileblock
[idx
].fileextent
,
mdp
->fileblock
[idx
].fnamep
,
* Check that the memoffset (offset in memory to start
* loading) is page alligned
if ((mdp
->fileblock
[idx
].memoffset
% pgsize
) != 0)
fatal("Offset 0x%llx into RAM for file %s is not "
"aligned with 0x%llx pagesize",
mdp
->fileblock
[idx
].memoffset
,
mdp
->fileblock
[idx
].fnamep
,
ASSERT(NULL
!= datap
|| (NULL
== datap
&&
0LL == mdp
->fileblock
[idx
].memoffset
));
DBG( PRINTF(("mapping %s (%s): 0x%llx -> 0x%llx (0x%llx)\n",
mdp
->fileblock
[idx
].fnamep
,
(is_shared
? "SHARED" : "PRIVATE"),
config_devp
->addrp
->baseaddr
+
mdp
->fileblock
[idx
].memoffset
,
config_devp
->addrp
->baseaddr
+
mdp
->fileblock
[idx
].memoffset
+
mdp
->fileblock
[idx
].fileextent
,
mdp
->fileblock
[idx
].fileextent
)); );
* mmap the file into memory with the appropriate flags.
mapp
= (void*)mmap((void*)(datap
+
mdp
->fileblock
[idx
].memoffset
),
mdp
->fileblock
[idx
].fileextent
,
(is_shared
? MAP_SHARED
: MAP_PRIVATE
) | MAP_FIXED
| MAP_NORESERVE
,
fd
, mdp
->fileblock
[idx
].fileoffset
);
if (((uint8_t *)MAP_FAILED
) == mapp
)
fatal("Failed mapping file %s",
mdp
->fileblock
[idx
].fnamep
);
ASSERT((datap
+ mdp
->fileblock
[idx
].memoffset
) == mapp
);
#if VDISK_SUPPORT /* { */
* Now we have mmaped in all files, we need to create a valid
* VTOC for the root disk (ie, the first file loaded) based on
* the size of the other disks. The VTOC also needs to have
* correct values for s2 (the entire disk) so that someone can
* open the label on s0 and figure out the size of the entire
* disk and the layout of each partition.
#endif /* VDISK_SUPPORT } */
for (cp
= mdp
->contentp
; cp
!= NULL
; cp
= next_cp
) {
memmove(mdp
->datap
+cp
->offset
, cp
->datap
, cp
->size
);
SANITY( mdp
->contentp
= NULL
; );
* Memory configuration dump
mem_dump(config_dev_t
*config_devp
)
* Returns the extent of the linear cacheable block
* starting at offset, and a pointer to the state block
* Note: if the device is a ROM, attempts to write
* i.e. DA_Store as type must be failed -
* the function is supposed to return 0.
mem_cacheable(config_addr_t
*config_addrp
, dev_access_t type
, tpaddr_t offset
,
mdp
= config_addrp
->config_devp
->devp
;
/* fail store attempts to a ROM */
if (mdp
->is_rom
&& (type
& DA_Store
))
#if VDISK_SUPPORT /* { */
/* cannot execute from a disk */
if (mdp
->is_disk
&& (type
& DA_Instn
))
#endif /* VDISK_SUPPORT } */
if ((offset
< 0) || (offset
>= config_addrp
->range
)) {
*blockp
= mdp
->datap
+ offset
;
return (config_addrp
->range
- offset
);
* Should only get invoked if this is a ROM.
* Indicate the store failed - return false
mem_cpu_access(simcpu_t
*sp
, config_addr_t
*cap
, tpaddr_t offset
, maccess_t op
,
mdp
= cap
->config_devp
->devp
;
EXEC_WARNING(("rom_cpu_store: attempted store to ROM @ pc 0x%llx "
"of %d bytes at offset 0x%llx",
sp
->pc
, 1<<(op
& MA_Size_Mask
), offset
));
#if VDISK_SUPPORT /* { */
dump_label(mem_dev_t
*mdp
)
struct dk_label
*dk_label
;
uint64_t nsect
, nhead
, nblocks
, cyl_size
;
uint64_t ncyl
, start_cyl
, end_cyl
, size
;
char tag_str
[15], flag_str
[15];
dk_label
= (struct dk_label
*)mdp
->datap
;
* If no magic, give up early
if (dk_label
->dkl_magic
!= DKL_MAGIC
) {
PRINTF(("No valid disk label - giving up\n"));
nsect
= dk_label
->dkl_nsect
;
nhead
= dk_label
->dkl_nhead
;
cyl_size
= nsect
* nhead
;
if (dk_label
->dkl_magic
!= DKL_MAGIC
) {
PRINTF(("Bad disk label\n"));
DBG( PRINTF(("[%4s] [%10s] [%4s] [%10s] - [%10s] [%15s] [%10s] [%10s]\n",
"part", "Tag", "Flag", "Start-Cyl", "End-Cyl", "Size", "#Blocks",
for (i
= 0; i
< NDKMAP
; i
++) {
nblocks
= (uint64_t)dk_label
->dkl_map
[i
].dkl_nblk
;
/* Check to avoid a fault if label is malformed */
ncyl
= nblocks
/ cyl_size
;
ncyl
= nblocks
; /* fake */
start_cyl
= dk_label
->dkl_map
[i
].dkl_cylno
;
tag
= dk_label
->dkl_vtoc
.v_part
[i
].p_tag
;
flag
= dk_label
->dkl_vtoc
.v_part
[i
].p_flag
;
if (dk_label
->dkl_map
[i
].dkl_nblk
== 0)
end_cyl
= (dk_label
->dkl_map
[i
].dkl_cylno
+ ncyl
) -1;
strcpy(tag_str
, "unassigned"); break;
strcpy(tag_str
, "boot"); break;
strcpy(tag_str
, "root"); break;
strcpy(tag_str
, "swap"); break;
strcpy(tag_str
, "usr"); break;
strcpy(tag_str
, "backup"); break;
strcpy(tag_str
, "UNKNOWN"); break;
strcpy(flag_str
, "wm"); break;
strcpy(flag_str
, "wu"); break;
strcpy(flag_str
, "rm"); break;
strcpy(flag_str
, "unknown"); break;
DBG( PRINTF(("[%4d] [%10s] [ %2s ] [%10llu] - [%10llu] [%15llu] [%10llu] [%10llu] %lluMB\n",
i
, tag_str
, flag_str
, start_cyl
, end_cyl
, size
, nblocks
,
ncyl
, size
/1024/1024)); );
DBG( PRINTF(("nparts = [0x%x]\n\n", dk_label
->dkl_vtoc
.v_nparts
)); );
create_label(mem_dev_t
*mdp
)
struct dk_label
*dk_label
;
uint64_t nsect
, nhead
, nblocks
, nblocksa
, cyl_size
, sblock
;
uint64_t ncyl
, start_cyl
, end_cyl
, size
;
char tag_str
[MAXNAMELEN
], flag_str
[MAXNAMELEN
];
uint64_t total_nblocks
= 0;
* Dump the existing label
DBG( PRINTF(("\nReading label from disk\n")); );
dk_label
= (struct dk_label
*)mdp
->datap
;
for (idx
= 0; idx
< NDKMAP
; idx
++) {
dk_label
->dkl_map
[idx
].dkl_nblk
= 0x0;
dk_label
->dkl_map
[idx
].dkl_cylno
= 0x0;
dk_label
->dkl_vtoc
.v_part
[idx
].p_tag
= 0x0;
dk_label
->dkl_vtoc
.v_part
[idx
].p_flag
= V_UNMNT
;
dk_label
->dkl_magic
= DKL_MAGIC
;
* read disk label from s0 and modify it
* fake sectors and head = 1 to avoid rounding errors
* when calculating cyl_no. Rounding errors make it
* almost impossible to make the cyl_no align with the
* memoffset we mmaped the file into. So we just make
* start cyl == start block
nsect
= dk_label
->dkl_nsect
;
nhead
= dk_label
->dkl_nhead
;
cyl_size
= nsect
* nhead
;
* Update the label at slice 0 with this info
DBG( PRINTF(("Creating new lable as follows:\n")); );
for (idx
= 0; idx
< mdp
->nfileblocks
; idx
++) {
static uint64_t next_cyl
= 0;
slice
= mdp
->fileblock
[idx
].disk_slice
;
* Use the real value for fileextent to calculate the
* number of blocks for this partition.
* Our next partition needs to be loaded on a page boundry
* so we use the page aligned value for fileextent (fileextenta)
* to calculate the number of aligned blocks (nblocksa)
* Use this to count the number of blocks needed to pad
* the partition so the next slice can be loaded on a
nblocks
= mdp
->fileblock
[idx
].fileextent
/ 512;
nblocksa
= mdp
->fileblock
[idx
].fileextenta
/ 512;
total_nblocks
+= nblocksa
;
* calculate start cyl based on the memoffset
* we used to map this file.
* memoffest is already page aligned.
sblock
= mdp
->fileblock
[idx
].memoffset
/ 512;
ncyl
= (float)sblock
/ (float)cyl_size
;
/* Set the number of blocks in this slice */
dk_label
->dkl_map
[slice
].dkl_nblk
= nblocks
;
/* Set the starting cylinder */
dk_label
->dkl_map
[slice
].dkl_cylno
= ncyl
;
DBG( PRINTF(("slice=[%d] name=[%s] size=[%llu][0x%llx] nblocks=[%llu] nblocksa=[%llu] ncyl=[%llu] nsect=[%llu] nhead=[%llu]\n",
mdp
->fileblock
[idx
].disk_slice
,
mdp
->fileblock
[idx
].fnamep
,
mdp
->fileblock
[idx
].fileextent
,
mdp
->fileblock
[idx
].fileextent
,
nblocks
, nblocksa
, ncyl
, nsect
, nhead
)); );
/* Set the p_tag, p_flag for each slice */
if (slice
== 1) { /* SWAP */
dk_label
->dkl_vtoc
.v_part
[slice
].p_tag
= 0x3;
dk_label
->dkl_vtoc
.v_part
[slice
].p_flag
= V_UNMNT
;
} else { /* all else set to ROOT */
dk_label
->dkl_vtoc
.v_part
[slice
].p_tag
= 0x2;
dk_label
->dkl_vtoc
.v_part
[slice
].p_flag
= 0x0;
* create a valid VTOC entry for slice 2 which reflects the total
* size of the virtual disk (with all partitions).
dk_label
->dkl_vtoc
.v_part
[2].p_tag
= 0x5; /* backup */
dk_label
->dkl_vtoc
.v_part
[2].p_flag
= V_UNMNT
; /* wu */
dk_label
->dkl_map
[2].dkl_cylno
= 0x0; /* always start at 0 */
dk_label
->dkl_map
[2].dkl_nblk
= total_nblocks
; /* entire disk */
dk_label
->dkl_magic
= DKL_MAGIC
;
DBG( PRINTF(("New Checksum = [0x%hx]\n", get_checksum(dk_label
, CK_MAKESUM
))); );
* Update checksum on disk
dk_label
->dkl_cksum
= get_checksum(dk_label
, CK_MAKESUM
);
DBG( PRINTF(("Dumping new label to be written to disk\n")); );
* Construct checksum for the new disk label
get_checksum(struct dk_label
*dk_label
, int mode
)
i
= sizeof (*dk_label
) / sizeof (*sp
);
* If we are generating a checksum, don't include the checksum
* Take the xor of all the half-words in the label.
#endif /* VDISK_SUPPORT } */