void aes128ctr(u8 *key, u8 *iv, u8 *in, u64 len, u8 *out) { AES_KEY k; u32 i; u8 ctr[16]; u64 tmp; memset(ctr, 0, 16); memset(&k, 0, sizeof k); AES_set_encrypt_key(key, 128, &k); for (i = 0; i < len; i++) { if ((i & 0xf) == 0) { AES_encrypt(iv, ctr, &k); // increase nonce tmp = be64(iv + 8) + 1; wbe64(iv + 8, tmp); if (tmp == 0) wbe64(iv, be64(iv) + 1); } *out++ = *in++ ^ ctr[i & 0x0f]; } }
static void decompress_pkg(void *ptr) { u32 meta_offset; u32 n_sections; u32 i; u64 offset; u64 size; int compressed; u8 *tmp; meta_offset = be32(pkg + 0x0c); n_sections = be32(pkg + meta_offset + 0x60 + 0xc); for (i = 0; i < n_sections; i++) { tmp = pkg + meta_offset + 0x80 + 0x30 * i; offset = be64(tmp); size = be64(tmp + 8); compressed = 0; if (be32(tmp + 0x2c) == 0x2) compressed = 1; if (compressed) { // XXX: is always only the last section compressed? if (i + 1 != n_sections) fail("weird pkg: not only last section is compressed"); decompress(pkg + offset, size, ptr, dec_size); } } }
static void unpack_content(const char *name) { u8 *tmp; u8 *decompressed; u64 offset; u64 size; u64 size_real; tmp = pkg + meta_offset + 0x80 + 0x30 * 2; offset = be64(tmp); size = be64(tmp + 8); size_real = dec_size - 0x80; if (be32(tmp + 0x2c) == 0x2) { decompressed = malloc(size_real); memset(decompressed, 0xaa, size_real); decompress(pkg + offset, size, decompressed, size_real); memcpy_to_file(name, decompressed, size_real); } else { memcpy_to_file(name, pkg + offset, size); } }
void BRSHA384(void *md48, const void *data, size_t len) { size_t i; uint64_t x[16], buf[] = { 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4 }; assert(md48 != NULL); assert(data != NULL || len == 0); for (i = 0; i < len; i += 128) { // process data in 128 byte blocks memcpy(x, (const uint8_t *)data + i, (i + 128 < len) ? 128 : len - i); if (i + 128 > len) break; _BRSHA512Compress(buf, x); } memset((uint8_t *)x + (len - i), 0, 128 - (len - i)); // clear remainder of x ((uint8_t *)x)[len - i] = 0x80; // append padding if (len - i >= 112) _BRSHA512Compress(buf, x), memset(x, 0, 128); // length goes to next block x[14] = 0, x[15] = be64((uint64_t)len*8); // append length in bits _BRSHA512Compress(buf, x); // finalize for (i = 0; i < 6; i++) buf[i] = be64(buf[i]); // endian swap memcpy(md48, buf, 48); // write to md mem_clean(x, sizeof(x)); mem_clean(buf, sizeof(buf)); }
int main(int argc, char *argv[]) { char *dir; if (argc != 2 && argc != 3) fail("usage: ungpkg filename.pkg [target]"); pkg = mmap_file(argv[1]); if (argc == 2) { dir = malloc(0x31); memset(dir, 0, 0x31); memset(dir, 0, 0x30); memcpy(dir, pkg + 0x30, 0x30); } else { dir = argv[2]; } MKDIR(dir, 0777); if (chdir(dir) != 0) fail("chdir(%s)", dir); offset = be64(pkg + 0x20); size = be64(pkg + 0x28); if (be16(pkg + 0x04) & 0x8000) decrypt_retail_pkg(); else decrypt_debug_pkg(); unpack_pkg(); return 0; }
void BRSHA512(void *md64, const void *data, size_t len) { size_t i; uint64_t x[16], buf[] = { 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 }; assert(md64 != NULL); assert(data != NULL || len == 0); for (i = 0; i < len; i += 128) { // process data in 128 byte blocks memcpy(x, (const uint8_t *)data + i, (i + 128 < len) ? 128 : len - i); if (i + 128 > len) break; _BRSHA512Compress(buf, x); } memset((uint8_t *)x + (len - i), 0, 128 - (len - i)); // clear remainder of x ((uint8_t *)x)[len - i] = 0x80; // append padding if (len - i >= 112) _BRSHA512Compress(buf, x), memset(x, 0, 128); // length goes to next block x[14] = 0, x[15] = be64((uint64_t)len*8); // append length in bits _BRSHA512Compress(buf, x); // finalize for (i = 0; i < 8; i++) buf[i] = be64(buf[i]); // endian swap memcpy(md64, buf, 64); // write to md mem_clean(x, sizeof(x)); mem_clean(buf, sizeof(buf)); }
static int verify_hash(u8 *p, u8 *hashes) { u64 offset; u64 size; u64 id; u8 *hash, *key; u8 result[20]; offset = be64(p + 0x00); size = be64(p + 0x08); id = be32(p + 0x1c); if (id == 0xffffffff) return 0; hash = hashes + id * 0x10; key = hash + 0x20; // XXX: possible integer overflow here if (offset > (filesize + header_len)) return 1; // XXX: possible integer overflow here if ((offset + size) > (filesize + header_len)) return 1; sha1_hmac(key, ptr + offset, size, result); if (memcmp(result, hash, 20) == 0) return 0; else return -1; }
static void decrypt_spkg(void) { u16 flags; u16 type; struct keylist *k; flags = be16(pkg + 0x08); type = be16(pkg + 0x0a); hdr_len = be64(pkg + 0x10); dec_size = be64(pkg + 0x18); if (type != 3) fail("no .spkg file"); k = keys_get(KEY_SPKG); if (k == NULL) fail("no key found"); if (sce_decrypt_header(pkg, k) < 0) fail("header decryption failed"); meta_offset = be32(pkg + 0x0c); n_sections = be32(pkg + meta_offset + 0x60 + 0xc); if (n_sections != 3) fail("invalid section count: %d", n_sections); }
static void read_spp_header(void) { flags = be16(ptr + 0x08); meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); filesize = be64(ptr + 0x18); klist = keys_get(KEY_SPP); }
static void read_pkg_header(u8* ptr, fileinfo* info) { info->flags = be16(ptr + 0x08); info->meta_offset = be32(ptr + 0x0c); info->header_len = be64(ptr + 0x10); info->filesize = be64(ptr + 0x18); klist = keys_get(KEY_PKG); }
int sce_remove_npdrm(u8 *ptr, struct keylist *klist) { u64 ctrl_offset; u64 ctrl_size; u32 block_type; u32 block_size; u32 license_type; char content_id[0x31] = {'\0'}; struct rif *rif; struct actdat *actdat; u8 enc_const[0x10]; u8 dec_actdat[0x10]; struct key klicensee; u64 i; ctrl_offset = be64(ptr + 0x58); ctrl_size = be64(ptr + 0x60); for (i = 0; i < ctrl_size; ) { block_type = be32(ptr + ctrl_offset + i); block_size = be32(ptr + ctrl_offset + i + 0x4); if (block_type == 3) { license_type = be32(ptr + ctrl_offset + i + 0x18); switch (license_type) { case 1: // cant decrypt network stuff return -1; case 2: memcpy(content_id, ptr + ctrl_offset + i + 0x20, 0x30); rif = rif_get(content_id); if (rif == NULL) { return -1; } aes128(klist->rif->key, rif->padding, rif->padding); aes128_enc(klist->idps->key, klist->npdrm_const->key, enc_const); actdat = actdat_get(); if (actdat == NULL) { return -1; } aes128(enc_const, &actdat->keyTable[swap32(rif->actDatIndex)*0x10], dec_actdat); aes128(dec_actdat, rif->key, klicensee.key); sce_decrypt_npdrm(ptr, klist, &klicensee); return 1; case 3: sce_decrypt_npdrm(ptr, klist, klist->free_klicensee); return 1; } } i += block_size; } return 0; }
static void read_self_header(void) { flags = be16(ptr + 0x08); meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); filesize = be64(ptr + 0x18); info_offset = be64(ptr + 0x28); app_type = be32(ptr + info_offset + 0x0c); klist = self_load_keys(); }
static void read_self_header(u8* ptr, fileinfo* info) { info->flags = be16(ptr + 0x08); info->meta_offset = be32(ptr + 0x0c); info->header_len = be64(ptr + 0x10); info->filesize = be64(ptr + 0x18); info->info_offset = be64(ptr + 0x28); info->app_type = be32(ptr + info->info_offset + 0x0c); klist = self_load_keys(info); }
static int header_check_qcow1(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) { const QCowHeader_t *header=(const QCowHeader_t*)buffer; uint64_t min_size=be64(header->backing_file_offset); if(min_size < be64(header->l1_table_offset)) min_size=be64(header->l1_table_offset); reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_cow.extension; file_recovery_new->time=be32(header->mtime); file_recovery_new->min_filesize=min_size; return 1; }
static void read_section(u32 i, struct self_sec *sec) { u8 *ptr; ptr = self + sec_offset + i*0x20; sec->idx = i; sec->offset = be64(ptr + 0x00); sec->size = be64(ptr + 0x08); sec->compressed = be32(ptr + 0x10) == 2 ? 1 : 0; sec->encrypted = be32(ptr + 0x20); sec->next = be64(ptr + 0x20); }
int paged_file_seek (PagedFile *f, u64 offset) { u32 pos; if (!f->reader) return -1; pos = offset % 0x10; offset &= ~0xF; if (offset + pos > f->page_pos && offset + pos < f->page_pos + f->size) { f->pos = offset + pos - f->page_pos; return f->page_pos + f->pos; } if (f->crypt != PAGED_FILE_CRYPT_NONE) { /* TODO: support other crypto */ if (f->crypt == PAGED_FILE_CRYPT_AES_128_CBC || f->crypt == PAGED_FILE_CRYPT_AES_256_CBC) { if (offset >= 0x10) { fseek (f->fd, offset - 0x10, SEEK_SET); if (fread (f->iv, 1, 0x10, f->fd) != 1) return -1; } } else if (f->crypt == PAGED_FILE_CRYPT_AES_128_CTR) { s64 seek_diff = (signed) (offset - (f->page_pos + f->size)) / 0x10; u64 tmp = be64(f->iv + 8) + seek_diff; if (seek_diff > 0 && tmp < be64 (f->iv + 8)) wbe64(f->iv, be64(f->iv) + 1); else if (seek_diff < 0 && tmp > be64 (f->iv + 8)) wbe64(f->iv, be64(f->iv) - 1); wbe64(f->iv + 8, tmp); } else if (f->crypt == PAGED_FILE_CRYPT_CUSTOM) { if (!f->crypt_cb (f, PAGED_FILE_CRYPT_SEEK, NULL, offset, f->crypt_cb_data)) return -1; } } fseek (f->fd, offset, SEEK_SET); f->size = 0; f->page_pos = ftell (f->fd); paged_file_read_new_page (f); f->pos = pos; return f->page_pos; }
int sce_encrypt_header(u8 *ptr, struct key *k) { u32 meta_offset; u32 meta_len; u64 header_len; u8 iv[16]; meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); meta_len = header_len - meta_offset; memcpy(iv, ptr + meta_offset + 0x40, 0x10); aes128ctr(ptr + meta_offset + 0x20, iv, ptr + meta_offset + 0x60, meta_len - 0x60, ptr + meta_offset + 0x60); aes256cbc_enc(k->key, k->iv, ptr + meta_offset + 0x20, 0x40, ptr + meta_offset + 0x20); return 0; }
void Unpup(const char* folder){ u32 i; char folder_2[200]; if(read_only!=1){ DIR *dip; i=0; do{ sprintf(folder_2,"%s_%u",folder,i++); }while((dip = opendir(folder_2)) != NULL); closedir(dip); MKDIR(folder_2, 0777); chdir(folder_2); } const char *file_name; if(read_only!=0) printf("Read Only Mode!\n"); printf("Reading...\n"); u64 HDR = be64(pup); if(HDR!=PSV_HDR) fail("\nERROR! Not a PlayStation Vita Update File (%08x%08x)",HDR>>32,HDR); u32 pkg_version = le32(pup+0x08); u32 img_version = le32(pup+0x10); file_count = le32(pup+0x18); u32 hdr_lenght = le32(pup+0x20); u32 pkg_lenght = le32(pup+0x28); dmsg("HDR 0x%08x%08x\n",HDR>>32,HDR); dmsg("PKG VERSION 0x%08x\n",pkg_version); dmsg("IMG VERSION 0x%08x\n",img_version); printf("N of Files %u\n",file_count); dmsg("HDR Lenght 0x%08x\n",hdr_lenght); dmsg("PKG Lenght 0x%08x\n",pkg_lenght); dmsg("Table Lenght 0x%08x\n",0x80+(0x20*file_count)); u32 entry,offset,size; for(i=0;i<file_count;i+=0x1){ entry = le32(pup+0x80+0x20*i); offset = le32(pup+0x80+0x20*i+0x08); size = le32(pup+0x80+0x20*i+0x10); file_name = id2name(entry, t_names, NULL); if(file_name==NULL){ dmsg("unknown entry id: 0x%08x | Offset: 0x%08x\n",entry,offset); snprintf(unknown_name,256,"unknown_data_0x%x_%02d.data",entry,unknown_type++); file_name = unknown_name; } printf("Found: %30s | size: %10u Bytes\n",file_name,size); if(read_only!=1) memcpy_to_file(file_name, pup + offset, size); } if(read_only!=1){ dmsg("Writing security_1.."); Write("security_1",0x30,0x50); } printf("Done!\n"); }
static void unpack_file(u32 i) { u8 *ptr; u8 name[33]; u64 offset; u64 size; ptr = pkg + 0x10 + 0x30 * i; offset = be64(ptr + 0x00); size = be64(ptr + 0x08); memset(name, 0, sizeof name); strncpy((char *)name, (char *)(ptr + 0x10), 0x20); printf("unpacking %s...\n", name); memcpy_to_file((char *)name, pkg + offset, size); }
// // ELF helpers // int elf_read_hdr(u8 *hdr, struct elf_hdr *h) { int arch64; memcpy(h->e_ident, hdr, 16); hdr += 16; arch64 = h->e_ident[4] == 2; h->e_type = be16(hdr); hdr += 2; h->e_machine = be16(hdr); hdr += 2; h->e_version = be32(hdr); hdr += 4; if (arch64) { h->e_entry = be64(hdr); h->e_phoff = be64(hdr + 8); h->e_shoff = be64(hdr + 16); hdr += 24; } else { h->e_entry = be32(hdr); h->e_phoff = be32(hdr + 4); h->e_shoff = be32(hdr + 8); hdr += 12; } h->e_flags = be32(hdr); hdr += 4; h->e_ehsize = be16(hdr); hdr += 2; h->e_phentsize = be16(hdr); hdr += 2; h->e_phnum = be16(hdr); hdr += 2; h->e_shentsize = be16(hdr); hdr += 2; h->e_shnum = be16(hdr); hdr += 2; h->e_shtrndx = be16(hdr); return arch64; }
int sce_decrypt_header(u8 *ptr, struct keylist *klist) { u32 meta_offset; u32 meta_len; u64 header_len; u32 i, j; u8 tmp[0x40]; int success = 0; meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); for (i = 0; i < klist->n; i++) { aes256cbc(klist->keys[i].key, klist->keys[i].iv, ptr + meta_offset + 0x20, 0x40, tmp); success = 1; for (j = 0x10; j < (0x10 + 0x10); j++) if (tmp[j] != 0) success = 0; for (j = 0x30; j < (0x30 + 0x10); j++) if (tmp[j] != 0) success = 0; if (success == 1) { memcpy(ptr + meta_offset + 0x20, tmp, 0x40); break; } } if (success != 1) return -1; printf(" Metadata key id: %s\n", klist->keys[i].id); memcpy(tmp, ptr + meta_offset + 0x40, 0x10); aes128ctr(ptr + meta_offset + 0x20, tmp, ptr + meta_offset + 0x60, 0x20, ptr + meta_offset + 0x60); meta_len = header_len - meta_offset; aes128ctr(ptr + meta_offset + 0x20, tmp, ptr + meta_offset + 0x80, meta_len - 0x80, ptr + meta_offset + 0x80); return i; }
static int header_check_cwk(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) { const struct cwk_header *cwk=(const struct cwk_header *)buffer; if(be64(cwk->reserved0)!=0 || be16(cwk->reserved1)!=1) return 0; reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_cwk.extension; file_recovery_new->file_check=&file_check_cwk; return 1; }
static void unpack_info(u32 i) { u8 *tmp; u64 offset; u64 size; char path[256]; tmp = pkg + meta_offset + 0x80 + 0x30 * i; snprintf(path, sizeof path, "info%d", i); offset = be64(tmp); size = be64(tmp + 8); if (size != 0x40) fail("weird info size: %08x", size); memcpy_to_file(path, pkg + offset, size); }
static int header_check_ecryptfs(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) { const struct ecrypfs_header *e=(const struct ecrypfs_header *)buffer; if((be32(e->marker1) ^ be32(e->marker2)) == 0x3c81b7f5) { reset_file_recovery(file_recovery_new); #ifdef DJGPP file_recovery_new->extension="ecr"; #else file_recovery_new->extension=file_hint_ecryptfs.extension; #endif file_recovery_new->min_filesize=be64(e->unencrypted_file_size); file_recovery_new->calculated_file_size=be64(e->unencrypted_file_size); file_recovery_new->data_check=NULL; file_recovery_new->file_check=&file_check_ecryptfs; return 1; } return 0; }
int sce_decrypt_header(uint8_t *ptr, struct keylist_t *klist) { uint32_t meta_offset; uint32_t meta_len; uint64_t header_len; uint32_t i, j; uint8_t tmp[0x40]; int success = 0; meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); for (i = 0; i < klist->n; i++) { AES_cbc256_decrypt(klist->keys[i].key, klist->keys[i].iv, ptr + meta_offset + 0x20, 0x40, tmp); success = 1; for (j = 0x10; j < (0x10 + 0x10); j++) if (tmp[j] != 0) success = 0; for (j = 0x30; j < (0x30 + 0x10); j++) if (tmp[j] != 0) success = 0; if (success == 1) { memcpy(ptr + meta_offset + 0x20, tmp, 0x40); break; } } if (success != 1) return -1; memcpy(tmp, ptr + meta_offset + 0x40, 0x10); AES_ctr128_encrypt(ptr + meta_offset + 0x20, tmp, ptr + meta_offset + 0x60, 0x20, ptr + meta_offset + 0x60); meta_len = header_len - meta_offset; AES_ctr128_encrypt(ptr + meta_offset + 0x20, tmp, ptr + meta_offset + 0x80, meta_len - 0x80, ptr + meta_offset + 0x80); return i; }
int sce_decrypt_data(uint8_t *ptr) { uint64_t meta_offset; uint32_t meta_len; uint32_t meta_n_hdr; uint64_t header_len; uint32_t i; uint64_t offset; uint64_t size; uint32_t keyid; uint32_t ivid; uint8_t *tmp; uint8_t iv[16]; meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); meta_len = header_len - meta_offset; meta_n_hdr = be32(ptr + meta_offset + 0x60 + 0xc); for (i = 0; i < meta_n_hdr; i++) { tmp = ptr + meta_offset + 0x80 + 0x30*i; offset = be64(tmp); size = be64(tmp + 8); keyid = be32(tmp + 0x24); ivid = be32(tmp + 0x28); if (keyid == 0xffffffff || ivid == 0xffffffff) continue; memcpy(iv, ptr + meta_offset + 0x80 + 0x30 * meta_n_hdr + ivid * 0x10, 0x10); AES_ctr128_encrypt(ptr + meta_offset + 0x80 + 0x30 * meta_n_hdr + keyid * 0x10, iv, ptr + offset, size, ptr + offset); } return 0; }
int sce_decrypt_data(u8 *ptr) { u64 meta_offset; u32 meta_len; u32 meta_n_hdr; u64 header_len; u32 i; u64 offset; u64 size; u32 keyid; u32 ivid; u8 *tmp; u8 iv[16]; meta_offset = be32(ptr + 0x0c); header_len = be64(ptr + 0x10); meta_len = header_len - meta_offset; meta_n_hdr = be32(ptr + meta_offset + 0x60 + 0xc); for (i = 0; i < meta_n_hdr; i++) { tmp = ptr + meta_offset + 0x80 + 0x30*i; offset = be64(tmp); size = be64(tmp + 8); keyid = be32(tmp + 0x24); ivid = be32(tmp + 0x28); if (keyid == 0xffffffff || ivid == 0xffffffff) continue; memcpy(iv, ptr + meta_offset + 0x80 + 0x30 * meta_n_hdr + ivid * 0x10, 0x10); aes128ctr(ptr + meta_offset + 0x80 + 0x30 * meta_n_hdr + keyid * 0x10, iv, ptr + offset, size, ptr + offset); } return 0; }
static void parse_pkg_1(void) { u32 n_files; u64 size; u32 i; n_files = be32(pkg + 4); size = be64(pkg + 8); for (i = 0; i < n_files; i++) unpack_file(i); }
void elf_read_shdr(int arch64, u8 *shdr, struct elf_shdr *s) { if (arch64) { s->sh_name = be32(shdr + 0*4); s->sh_type = be32(shdr + 1*4); s->sh_flags = be64(shdr + 2*4); s->sh_addr = be64(shdr + 2*4 + 1*8); s->sh_offset = be64(shdr + 2*4 + 2*8); s->sh_size = be64(shdr + 2*4 + 3*8); s->sh_link = be32(shdr + 2*4 + 4*8); s->sh_info = be32(shdr + 3*4 + 4*8); s->sh_addralign = be64(shdr + 4*4 + 4*8); s->sh_entsize = be64(shdr + 4*4 + 5*8); } else { s->sh_name = be32(shdr + 0*4); s->sh_type = be32(shdr + 1*4); s->sh_flags = be32(shdr + 2*4); s->sh_addr = be32(shdr + 3*4); s->sh_offset = be32(shdr + 4*4); s->sh_size = be32(shdr + 5*4); s->sh_link = be32(shdr + 6*4); s->sh_info = be32(shdr + 7*4); s->sh_addralign = be32(shdr + 8*4); s->sh_entsize = be32(shdr + 9*4); } }
int xfs_gfun(disk_desc *d, g_module *m) { xfs_sb_t *sb; s64_t size; m->m_guess = GM_NO; sb = (xfs_sb_t *)d->d_sbuf; /* * Sanity checks from xfs_mount.c */ if (be32(sb->sb_magicnum) != XFS_SB_MAGIC) return (1); if (be32(sb->sb_blocksize) != getpagesize()) return (1); if ((sb->sb_imax_pct > 100) || (sb->sb_sectsize <= 0)) return (1); if ((be16(sb->sb_inodesize) < XFS_DINODE_MIN_SIZE) || (be16(sb->sb_inodesize) > XFS_DINODE_MAX_SIZE)) return (1); if (be32(sb->sb_blocksize) != 1 << sb->sb_blocklog) return (1); size = be64(sb->sb_logstart) ? (s64_t)be32(sb->sb_logblocks) : 0LL; size = be64(sb->sb_dblocks) - size; size *= be32(sb->sb_blocksize); size /= d->d_ssize; m->m_guess = GM_YES; m->m_part.p_start = d->d_nsb; m->m_part.p_size = (unsigned long)size; m->m_part.p_typ = 0x83; return (1); }