- vp = NULL;
- header = NULL;
- orig_mh = NULL;
- orig_st = NULL;
-
- // Dispose of unnecessary gumf, the booter doesn't need to load these
- rc_mh = IODTGetLoaderInfo("Kernel-__HEADER",
- (void **)&orig_mh, &orig_mhsize);
- if (rc_mh == 0 && orig_mh)
- IODTFreeLoaderInfo("Kernel-__HEADER",
- (void *)orig_mh, round_page_32(orig_mhsize));
-
- rc_sc = IODTGetLoaderInfo("Kernel-__SYMTAB",
- (void **) &orig_st, &orig_st_size);
- if (rc_sc == 0 && orig_st)
- IODTFreeLoaderInfo("Kernel-__SYMTAB",
- (void *)orig_st, round_page_32(orig_st_size));
-
- if (pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid)
- goto out;
-
- // Check to see if the root is 'e' or 'n', is this a test for network?
- if (rootdevice[0] == 'e' && rootdevice[1] == 'n')
- goto out;
-
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "mach.sym", p);
- if((error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IRGRP | S_IROTH))) goto out;
-
- vp = nd.ni_vp;
-
- /* Don't dump to non-regular files or files with links. */
- error = EFAULT;
- if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p)
- || vattr.va_nlink != 1)
- goto out;
-
- VATTR_NULL(&vattr);
- vattr.va_size = 0;
- VOP_LEASE(vp, p, cred, LEASE_WRITE);
- VOP_SETATTR(vp, &vattr, cred, p);
- p->p_acflag |= ACORE;
-
- // If the file type is MH_EXECUTE then this must be a kernel
- // as all Kernel extensions must be of type MH_OBJECT
- orig_ds = orig_ts = orig_le = NULL;
- orig_st = NULL;
- orig_mh = &_mh_execute_header;
- cmd = (struct load_command *) &orig_mh[1];
- for (i = 0; i < orig_mh->ncmds; i++) {
- if (cmd->cmd == LC_SEGMENT) {
- struct segment_command *sg = (struct segment_command *) cmd;
-
- if (!strcmp(SEG_TEXT, sg->segname))
- orig_ts = sg;
- else if (!strcmp(SEG_DATA, sg->segname))
- orig_ds = sg;
- else if (!strcmp(SEG_LINKEDIT, sg->segname))
- orig_le = sg;
+static int device_ioctl(void * p1, __unused void * p2, u_long theIoctl, caddr_t result)
+{
+ return (VNOP_IOCTL(p1, theIoctl, result, 0, p2));
+}
+
+static int
+kern_ioctl_file_extents(struct kern_direct_file_io_ref_t * ref, u_long theIoctl, off_t offset, off_t end)
+{
+ int error;
+ int (*do_ioctl)(void * p1, void * p2, u_long theIoctl, caddr_t result);
+ void * p1;
+ void * p2;
+ uint64_t fileblk;
+ size_t filechunk;
+ dk_extent_t extent;
+ dk_unmap_t unmap;
+ _dk_cs_pin_t pin;
+
+ bzero(&extent, sizeof(dk_extent_t));
+ bzero(&unmap, sizeof(dk_unmap_t));
+ bzero(&pin, sizeof(pin));
+ if (ref->vp->v_type == VREG)
+ {
+ p1 = &ref->device;
+ p2 = kernproc;
+ do_ioctl = &file_ioctl;
+ }
+ else
+ {
+ /* Partition. */
+ p1 = ref->vp;
+ p2 = ref->ctx;
+ do_ioctl = &device_ioctl;
+ }
+ while (offset < end)
+ {
+ if (ref->vp->v_type == VREG)
+ {
+ daddr64_t blkno;
+ filechunk = 1*1024*1024*1024;
+ if (filechunk > (size_t)(end - offset))
+ filechunk = (size_t)(end - offset);
+ error = VNOP_BLOCKMAP(ref->vp, offset, filechunk, &blkno, &filechunk, NULL, 0, NULL);
+ if (error) break;
+ fileblk = blkno * ref->blksize;
+ }
+ else if ((ref->vp->v_type == VBLK) || (ref->vp->v_type == VCHR))
+ {
+ fileblk = offset;
+ filechunk = ref->filelength;
+ }
+
+ if (DKIOCUNMAP == theIoctl)
+ {
+ extent.offset = fileblk;
+ extent.length = filechunk;
+ unmap.extents = &extent;
+ unmap.extentsCount = 1;
+ error = do_ioctl(p1, p2, theIoctl, (caddr_t)&unmap);
+// printf("DKIOCUNMAP(%d) 0x%qx, 0x%qx\n", error, extent.offset, extent.length);