X-Git-Url: http://git.ozlabs.org/?p=yaboot.git;a=blobdiff_plain;f=second%2Fprom.c;h=5aa0a02830f7dbe83d1dae968fca64878c3d1a5a;hp=3407e5ace7d936425503ad149b69ce3b40e99103;hb=2c611ced5c7fa551d47da32e574bc7f2ff2df18b;hpb=5d4289bddaef010cc14bcbeecfd13d5068b50a8e diff --git a/second/prom.c b/second/prom.c index 3407e5a..5aa0a02 100644 --- a/second/prom.c +++ b/second/prom.c @@ -33,6 +33,7 @@ #include "asm/processor.h" #include "errors.h" #include "debug.h" +#include "string.h" #define READ_BLOCKS_USE_READ 1 @@ -40,8 +41,6 @@ prom_entry prom; ihandle prom_stdin, prom_stdout; -//extern int vsprintf(char *buf, const char *fmt, va_list args); - static ihandle prom_mem, prom_mmu; static ihandle prom_chosen, prom_options; @@ -388,16 +387,14 @@ prom_readblocks (prom_handle dev, int blockNum, int blockCount, void *buffer) int prom_getchar () { - char c[4]; + char c; int a; - while ((a = (int)call_prom ("read", 3, 1, prom_stdin, c, 4)) == 0) + while ((a = (int)call_prom ("read", 3, 1, prom_stdin, &c, 1)) == 0) ; if (a == -1) prom_abort ("EOF on console\n"); - if (a == 3 && c[0] == '\e' && c[1] == '[') - return 0x100 | c[2]; - return c[0]; + return c; } int @@ -512,8 +509,6 @@ prom_readline (char *prompt, char *buf, int len) while (i < len-1 && (c = prom_getchar ()) != '\r') { - if (c >= 0x100) - continue; if (c == 8) { if (i > 0) @@ -567,6 +562,25 @@ prom_sleep (int seconds) while (prom_getms() <= end); } +/* if address given is claimed look for other addresses to get the needed + * space before giving up + */ +void * +prom_claim_chunk(void *virt, unsigned int size, unsigned int align) +{ + void *found, *addr; + for(addr=virt; addr <= (void*)PROM_CLAIM_MAX_ADDR; + addr+=(0x100000/sizeof(addr))) { + found = prom_claim(addr, size, 0); + if (found != (void *)-1) { + DEBUG_F("claimed %i at 0x%x (0x%x)\n",size,(int)found,(int)virt); + return(found); + } + } + prom_printf("Claim error, can't allocate %x at 0x%x\n",size,(int)virt); + return((void*)-1); +} + void * prom_claim (void *virt, unsigned int size, unsigned int align) { @@ -577,25 +591,6 @@ void prom_release(void *virt, unsigned int size) { call_prom ("release", 2, 0, virt, size); -#if 0 /* this is bullshit, newworld OF RELEASE method works fine. */ - - /* release in not enough, it needs also an unmap call. This bit of forth - * code inspired from Darwin's bootloader but could be replaced by direct - * calls to the MMU package if needed - */ - call_prom ("interpret", 3, 1, -#if DEBUG - ".\" ReleaseMem:\" 2dup . . cr " -#endif - "over \" translate\" ^mmu " // Find out physical base - "^on0 " // Bail if translation failed - "drop " // Leaving phys on top of stack - "2dup \" unmap\" ^mmu " // Unmap the space first - "2dup \" release\" ^mmu " // Then free the virtual pages - "\" release\" ^mem " // Then free the physical pages - ,size, virt - ); -#endif /* bullshit */ } void @@ -654,6 +649,106 @@ prom_pause(void) call_prom("enter", 0, 0); } +/* + * prom_get_netinfo() + * returns the packet with all needed info for netboot + */ +struct bootp_packet * prom_get_netinfo (void) +{ + void *bootp_response = NULL; + char *propname; + struct bootp_packet *packet; + /* struct bootp_packet contains a VLA, so sizeof won't work. + the VLA /must/ be the last field in the structure so use it's + offset as a good estimate of the packet size */ + size_t packet_size = offsetof(struct bootp_packet, options); + int i = 0, size, offset = 0; + prom_handle chosen; +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + + chosen = prom_finddevice("/chosen"); + if (chosen < 0) { + DEBUG_F("chosen=%d\n", chosen); + return 0; + } + + for (i = 0; i < ARRAY_SIZE(bootp_response_properties); i++) { + propname = bootp_response_properties[i].name; + size = prom_getproplen(chosen, propname); + if (size <= 0) + continue; + + DEBUG_F("using /chosen/%s\n", propname); + offset = bootp_response_properties[i].offset; + break; + } + + if (size <= 0) + return NULL; + + if (packet_size > size - offset) { + prom_printf("Malformed %s property?\n", propname); + return NULL; + } + + bootp_response = malloc(size); + if (!bootp_response) + return NULL; + + if (prom_getprop(chosen, propname, bootp_response, size) < 0) + return NULL; + + packet = bootp_response + offset; + return packet; +} + +/* + * prom_get_mac() + * returns the mac addr of an net card + */ +char * prom_get_mac (struct bootp_packet * packet) +{ + char * conf_path; + int i; + + if (!packet) + return NULL; + + /* 3 chars per byte in chaddr + \0 */ + conf_path = malloc(packet->hlen * 3 + 1); + if (!conf_path) + return NULL; + sprintf(conf_path, "%02x", packet->chaddr[0]); + + for (i = 1; i < packet->hlen; i++) { + char tmp[4]; + sprintf(tmp, "-%02x", packet->chaddr[i]); + strcat(conf_path, tmp); + } + + return conf_path; +} + +/* + * prom_get_ip() + * returns the ip addr of an net card + */ +char * prom_get_ip (struct bootp_packet * packet) +{ + char * conf_path; + + if (!packet) + return NULL; + + /* 8 chars in yiaddr + \0 */ + conf_path = malloc(9); + if (!conf_path) + return NULL; + sprintf(conf_path, "%08x", packet->yiaddr); + + return conf_path; +} + /* * Local variables: * c-file-style: "k&r"