void axfs_map_physmem(struct axfs_super *sbi, unsigned long size) { void *addr; if (axfs_is_physmem(sbi)) { addr = AXFS_REMAP(sbi->phys_start_addr, size); sbi->virt_start_addr = (unsigned long)addr; } }
/****************************************************************************** * * axfs_fetch_mmapable_data * * Description: * Fetches pages of data. Only called when a page is in the mmaped region. * * Parameters: * (IN) sbi- axfs superblock pointer * * (IN) fofffset - offset from the beginning of the filesystem * * (IN) len - length to be fetched * * Returns: * a vmalloc()'ed pointer with a copy of the requested data * *****************************************************************************/ static void *axfs_fetch_mmapable_data(struct axfs_super_incore *sbi, u64 fsoffset, u64 len) { unsigned long addr; void *copy_buffer; void *return_buffer; return_buffer = vmalloc((size_t)len); if(AXFS_PHYSADDR_IS_VALID(sbi)) { addr = sbi->phys_start_addr + (unsigned long)fsoffset; copy_buffer = AXFS_REMAP(addr, (unsigned long)len); memcpy(return_buffer, copy_buffer, (size_t)len); AXFS_UNMAP(copy_buffer); } else { addr = sbi->virt_start_addr + (unsigned long)fsoffset; memcpy(return_buffer, (void *)addr, (size_t)len); } return return_buffer; }
/****************************************************************************** * * axfs_get_sb_physaddr * * Description: * Populates a axfs_fill_super_info struct after sanity checking physaddr * * Parameters: * (IN) physaddr - the physical address of to check * * Returns: * pointer to a axfs_file_super_info or an error pointer * *****************************************************************************/ static struct axfs_fill_super_info * axfs_get_sb_physaddr(unsigned long physaddr) { void *buffer; struct axfs_fill_super_info *output; int err = -EINVAL; if (physaddr == 0) goto out; if (physaddr & (PAGE_SIZE - 1)) { printk(KERN_ERR "axfs: physical address 0x%lx for axfs image isn't aligned to a page boundary\n", physaddr); goto out; } printk(KERN_INFO "axfs: checking physical address 0x%lx for axfs image\n", physaddr); buffer = AXFS_REMAP(physaddr, PAGE_SIZE); if(buffer == NULL) { printk(KERN_ERR "axfs: ioremap() failed at physical address 0x%lx\n", physaddr); goto out; } output = (struct axfs_fill_super_info *) vmalloc(sizeof(struct axfs_fill_super_info)); output->onmedia_super_block = (struct axfs_super_onmedia *) vmalloc(sizeof(struct axfs_super_onmedia)); memcpy((void *)output->onmedia_super_block, (void *)buffer, sizeof(struct axfs_super_onmedia)); iounmap(buffer); output->physical_start_address = physaddr; output->virtual_start_address = 0; return output; out: return ERR_PTR(err); }
/****************************************************************************** * * axfs_do_fill_data_ptrs * * Description: * Fills the incore region descriptor with data from the onmedia version. * Processes the region to populate virt_addr by mapping to the physical * address or copying the data to RAM or if the data can be fetched later, * it is set to NULL. * * Parameters: * (IN) sb - pointer to the super block on media * * (IN) region_desc_offset - offset to the region descriptor from the * beginning of filesystem * * (OUT) iregion - pointer to the in RAM copy of the region descriptor * * (IN) force_va - if true the region must have a valid virt_addr * * Returns: * 0 or error number * *****************************************************************************/ static int axfs_do_fill_data_ptrs(struct super_block *sb, u64 region_desc_offset, struct axfs_region_desc_incore *iregion, int force_va) { struct axfs_super_incore *sbi; struct axfs_region_desc_onmedia *oregion; unsigned long addr; void *mapped = NULL; int err; u64 size; u64 end; u64 struct_len = sizeof(*oregion); sbi = AXFS_SB(sb); oregion = (struct axfs_region_desc_onmedia *) axfs_fetch_data(sb,region_desc_offset,struct_len); iregion->fsoffset = be64_to_cpu(oregion->fsoffset); iregion->size = be64_to_cpu(oregion->size); iregion->compressed_size = be64_to_cpu(oregion->compressed_size); iregion->max_index = be64_to_cpu(oregion->max_index); iregion->table_byte_depth = oregion->table_byte_depth; iregion->incore = oregion->incore; vfree(oregion); if (iregion->size == 0) return 0; end = iregion->fsoffset + iregion->size; if( (AXFS_IS_REGION_XIP(sbi,iregion)) && !(force_va && (sbi->mmap_size < end)) ) { if(AXFS_PHYSADDR_IS_VALID(sbi) ) { addr = sbi->phys_start_addr; addr += (unsigned long)iregion->fsoffset; size = (sbi->mmap_size > (iregion->fsoffset + iregion->size)) ? iregion->size : (sbi->mmap_size - iregion->fsoffset); iregion->virt_addr = AXFS_REMAP(addr,size); } else { addr = sbi->virt_start_addr; addr += (unsigned long)iregion->fsoffset; iregion->virt_addr = (void *)addr; } } else if(AXFS_IS_REGION_INCORE(iregion) || AXFS_IS_REGION_COMPRESSED(iregion) || force_va) { iregion->virt_addr = vmalloc(iregion->size); if(!(iregion->virt_addr)) { err = -ENOMEM; goto out; } if(AXFS_IS_REGION_COMPRESSED(iregion)) { mapped = axfs_fetch_data(sb,iregion->fsoffset,iregion->compressed_size); err = axfs_uncompress_block(iregion->virt_addr,iregion->size,mapped,iregion->compressed_size); if (err) goto out; } else { mapped = axfs_fetch_data(sb,iregion->fsoffset,iregion->size); memcpy(iregion->virt_addr,mapped,iregion->size); } } else { iregion->virt_addr = NULL; } if(mapped) vfree(mapped); return 0; out: if(mapped) vfree(mapped); if(iregion->virt_addr) vfree(iregion->virt_addr); return err; }