On Fri, Apr 4, 2008 at 3:45 AM, Peter Teoh <htmldeveloper@xxxxxxxxx> wrote: > This question was unanswered since Dec 2007 in the MM forum, someone can > help? > > http://forum.kernelnewbies.org/read.php?13,119 > > I am trying to access a 64KB block of NVRAM (BBR) placed at 0xe0000. For > lack of a better method I am using a linker command script to define a new > section for the BBR and hacking the kernel memory management so that a page > fault to the BBR data virtual address will force a page table entry > containing 0xe0000. I doubt this is the best way to achieve this, but after > posting to various linux forums, I have not been made aware of a better way. > Anyway, it seems to work - almost. The test application listed at the bottom > of this post, shows how I can write to the NVRAM simply using; > > BBR_char_data[0] = 'z'; > > However, attempting to reference the same variable to read the same > location using; > > printf("\nBBR_char_data = %X", (unsigned char)BBR_char_data[0]); > > merely displays 0xff. I know am writing to the location with the first > statement, because I can verify the new contents using another test utility. > > I would be grateful for any advice on what I need to do to successfully > read the variable BBR_char_data without using mmap. > > Thanks > > Mark > > linker command script > ==================== > . > . > . > MEMORY > { > MAIN_MEM (RWX) : ORIGIN = 0x08048000 + 1024, LENGTH = 128M > BBRDATA (RW) : ORIGIN = 0x10048000, LENGTH = 64K > } > . > . > . > .bbrdata (NOLOAD) : { *(.bbrdata) } > BBRDATA > . > . > . > > ------------------------------------------------------------------------------------- > kernel-source-2.4.27/mm/memory.c > ================================ > > static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * > vma, pte_t *page_table, int write_access, unsigned long addr) > { > pte_t entry; > > /* Read-only mapping of ZERO_PAGE. */ > entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot)); > > /* ..except if it's a write access */ > if (write_access) { > struct page *page; > > /* Allocate our own private page. */ > spin_unlock(&mm->page_table_lock); > > page = alloc_page(GFP_HIGHUSER); > > if (!page) > goto no_mem; > clear_user_highpage(page, addr); > > spin_lock(&mm->page_table_lock); > if (!pte_none(*page_table)) { > page_cache_release(page); > spin_unlock(&mm->page_table_lock); > return 1; > } > mm->rss++; > flush_page_to_ram(page); > > /* if( addr >= 0x10048000 && addr <= 0x10048800) > { > entry = pte_mkwrite(pte_mkdirty(mk_pte_phys(0xe0000, > vma->vm_page_prot))); // NVRAM is located at > // 0xe0000 > }*/ > else > { > entry = pte_mkwrite(pte_mkdirty(mk_pte(page, > vma->vm_page_prot))); > } > lru_cache_add(page); > mark_page_accessed(page); > } > > set_pte(page_table, entry); > > /* No need to invalidate - it was non-present before */ > update_mmu_cache(vma, addr, entry); > spin_unlock(&mm->page_table_lock); > return 1; /* Minor fault */ > > no_mem: > return -1; > } > > -------------------------------------------------------------------------------------------------------------------------------------------------------- > test utility > ============ > > #include <stdio.h> > #include <stdlib.h> > #include <string.h> > > > char BBR_char_data[0x10000] __attribute__ ((section (".bbrdata"winking > smiley)); > > int main(int argc, char *argv[]) > { > // this actually works and sets the first location of NVRAM to 'z' > BBR_char_data[0] = 'z'; > > // this doesn't work... it returns 0xff > printf("\nBBR_char_data = %X", (unsigned char)BBR_char_data[0]); > > return EXIT_SUCCESS; > } > > > -- > To unsubscribe from this list: send an email with > "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx > Please read the FAQ at http://kernelnewbies.org/FAQ > > Just out of curiosity, why the conversion to an unsigned int and translation to hex via the %X printf format parameter? Are you looking for the output '7A' (which is the hex value of 122... 122 being the base 10 value of 'z' on the ascii chart). 0XFF (255) can't be an ascii value, but it is the max value of an unsigned char. Just something I happened to come across in man (3) printf - The length modifier Here, `integer conversion' stands for d, i, o, u, x, or X conversion. [...] z A following integer conversion corresponds to a size_t or ssize_t argument. (Linux libc5 has Z with this meaning. Don't use it.) [...] The conversion specifier A character that specifies the type of conversion to be applied. The conversion specifiers and their meanings are: [...] o,u,x,X The unsigned int argument is converted to unsigned octal (o), unsigned decimal (u), or unsigned hexadecimal (x and X) notation. The letters abcdef are used for x conversions; the letters ABCDEF are used for X conversions. The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it is padded on the left with zeros. The default precision is 1. When 0 is printed with an explicit precision 0, the output is empty. I don't have enough time to look in to it (writing a paper on LDAP for class... ugh), but I find the coincidence that 'z' is size_t, and you're getting the correctly converted size_t of an unsigned char as your output, extremely unlikely. There seems to be quite a few notes in man printf(3) talking about different glibc and libc problems, this might also be something to look at.... Sorry I can't be of more help ATM. FWIW, I ran the test just fine on a Slackware-12 proper and it seemed alright. Perhaps you could try something besides 'z' and see if it is indeed a library bug. -- Peace and Blessings, -Scott. -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ