Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / ieee1394 / csr1212.c
index 7c4330e..1577354 100644 (file)
@@ -209,7 +209,15 @@ void csr1212_init_local_csr(struct csr1212_csr *csr,
 {
        static const int mr_map[] = { 4, 64, 1024, 0 };
 
+#ifdef __KERNEL__
+       BUG_ON(max_rom & ~0x3);
        csr->max_rom = mr_map[max_rom];
+#else
+       if (max_rom & ~0x3) /* caller supplied invalid argument */
+               csr->max_rom = 0;
+       else
+               csr->max_rom = mr_map[max_rom];
+#endif
        memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len);
 }
 
@@ -533,12 +541,15 @@ struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version,
        static const int pd[4] = { 0, 4, 16, 256 };
        static const int cs[16] = { 4, 2 };
        struct csr1212_keyval *kv;
-       int palette_size = pd[palette_depth] * cs[color_space];
+       int palette_size;
        int pixel_size = (hscan * vscan + 3) & ~0x3;
 
-       if ((palette_depth && !palette) || !pixels)
+       if (!pixels || (!palette && palette_depth) ||
+           (palette_depth & ~0x3) || (color_space & ~0xf))
                return NULL;
 
+       palette_size = pd[palette_depth] * cs[color_space];
+
        kv = csr1212_new_descriptor_leaf(1, 0, NULL,
                                         palette_size + pixel_size +
                                         CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD);
@@ -760,9 +771,9 @@ static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize)
        struct csr1212_csr_rom_cache *cache;
        u_int64_t csr_addr;
 
-       if (!csr || !csr->ops->allocate_addr_range ||
-           !csr->ops->release_addr)
-               return CSR1212_ENOMEM;
+       if (!csr || !csr->ops || !csr->ops->allocate_addr_range ||
+           !csr->ops->release_addr || csr->max_rom < 1)
+               return CSR1212_EINVAL;
 
        /* ROM size must be a multiple of csr->max_rom */
        romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);
@@ -1145,6 +1156,8 @@ int csr1212_generate_csr_image(struct csr1212_csr *csr)
 
                        /* Make sure the Extended ROM leaf is a multiple of
                         * max_rom in size. */
+                       if (csr->max_rom < 1)
+                               return CSR1212_EINVAL;
                        leaf_size = (cache->len + (csr->max_rom - 1)) &
                                ~(csr->max_rom - 1);
 
@@ -1248,7 +1261,7 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
                return CSR1212_EINVAL;
 #endif
 
-       cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+       cr = CSR1212_MALLOC(sizeof(*cr));
        if (!cr)
                return CSR1212_ENOMEM;
 
@@ -1380,8 +1393,7 @@ int csr1212_parse_keyval(struct csr1212_keyval *kv,
        case CSR1212_KV_TYPE_LEAF:
                if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
                        kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
-                       if (!kv->value.leaf.data)
-                       {
+                       if (!kv->value.leaf.data) {
                                ret = CSR1212_ENOMEM;
                                goto fail;
                        }
@@ -1409,7 +1421,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
        u_int32_t *cache_ptr;
        u_int16_t kv_len = 0;
 
-       if (!csr || !kv)
+       if (!csr || !kv || csr->max_rom < 1)
                return CSR1212_EINVAL;
 
        /* First find which cache the data should be in (or go in if not read
@@ -1449,7 +1461,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
                cache->next = NULL;
                csr->cache_tail = cache;
                cache->filled_head =
-                       CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+                       CSR1212_MALLOC(sizeof(*cache->filled_head));
                if (!cache->filled_head) {
                        return CSR1212_ENOMEM;
                }
@@ -1471,7 +1483,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
        /* Now seach read portions of the cache to see if it is there. */
        for (cr = cache->filled_head; cr; cr = cr->next) {
                if (cache_index < cr->offset_start) {
-                       newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+                       newcr = CSR1212_MALLOC(sizeof(*newcr));
                        if (!newcr)
                                return CSR1212_ENOMEM;
 
@@ -1495,7 +1507,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
 
        if (!cr) {
                cr = cache->filled_tail;
-               newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+               newcr = CSR1212_MALLOC(sizeof(*newcr));
                if (!newcr)
                        return CSR1212_ENOMEM;
 
@@ -1572,7 +1584,7 @@ int csr1212_parse_csr(struct csr1212_csr *csr)
        struct csr1212_dentry *dentry;
        int ret;
 
-       if (!csr || !csr->ops->bus_read)
+       if (!csr || !csr->ops || !csr->ops->bus_read)
                return CSR1212_EINVAL;
 
        ret = csr1212_parse_bus_info_block(csr);
@@ -1581,9 +1593,13 @@ int csr1212_parse_csr(struct csr1212_csr *csr)
 
        if (!csr->ops->get_max_rom)
                csr->max_rom = mr_map[0];       /* default value */
-       else
-               csr->max_rom = mr_map[csr->ops->get_max_rom(csr->bus_info_data,
-                                                           csr->private)];
+       else {
+               int i = csr->ops->get_max_rom(csr->bus_info_data,
+                                             csr->private);
+               if (i & ~0x3)
+                       return CSR1212_EINVAL;
+               csr->max_rom = mr_map[i];
+       }
 
        csr->cache_head->layout_head = csr->root_kv;
        csr->cache_head->layout_tail = csr->root_kv;
@@ -1594,15 +1610,17 @@ int csr1212_parse_csr(struct csr1212_csr *csr)
        csr->root_kv->valid = 0;
        csr->root_kv->next = csr->root_kv;
        csr->root_kv->prev = csr->root_kv;
-       csr1212_get_keyval(csr, csr->root_kv);
+       ret = _csr1212_read_keyval(csr, csr->root_kv);
+       if (ret != CSR1212_SUCCESS)
+               return ret;
 
        /* Scan through the Root directory finding all extended ROM regions
         * and make cache regions for them */
        for (dentry = csr->root_kv->value.directory.dentries_head;
             dentry; dentry = dentry->next) {
-               if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
-                       csr1212_get_keyval(csr, dentry->kv);
-
+               if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM &&
+                       !dentry->kv->valid) {
+                       ret = _csr1212_read_keyval(csr, dentry->kv);
                        if (ret != CSR1212_SUCCESS)
                                return ret;
                }